Aracılığıyla paylaş


Öğretici: Java'da normal ifadeleri (regex) kullanarak dize arama

Şunlar için geçerlidir: SQL Server 2019 (15.x) ve sonraki sürümleri

Bu öğreticide SQL Server'dan iki sütun (kimlik ve metin) ve giriş parametresi olarak normal ifade (regex) alan bir Java sınıfı oluşturmak için SQL Server Dil Uzantıları'nın nasıl kullanılacağı gösterilmektedir. sınıfı, SQL Server'a (kimlik ve metin) iki sütun döndürür.

Java sınıfına gönderilen metin sütunundaki belirli bir metin için kod, verilen normal ifadenin yerine getirilip getirildiğini denetler ve bu metni özgün kimlikle birlikte döndürür.

Bu örnek kod, bir metnin veya javasözcüğünü Java içerip içermediğini denetleen normal bir ifade kullanır.

Önkoşullar

kullanarak javac komut satırı derlemesi bu öğretici için yeterlidir.

Örnek veri oluşturma

İlk olarak yeni bir veritabanı oluşturun ve bir testdata tabloyu ve text sütunlarıyla ID doldurun.

CREATE DATABASE javatest;
GO

USE javatest;
GO

CREATE TABLE testdata
(
    [id] INT NOT NULL,
    [text] NVARCHAR (100) NOT NULL
);
GO

-- Insert data into test table
INSERT INTO testdata ([id], [text]) VALUES (1, 'This sentence contains java');
INSERT INTO testdata ([id], [text]) VALUES (2, 'This sentence does not');
INSERT INTO testdata ([id], [text]) VALUES (3, 'I love Java!');
GO

Ana sınıfı oluşturma

Bu adımda adlı RegexSample.java bir sınıf dosyası oluşturun ve aşağıdaki Java kodunu bu dosyaya kopyalayın.

Bu ana sınıf SDK'yı içeri aktarıyor, yani 1. adımda indirilen jar dosyasının bu sınıftan bulunabilir olması gerekiyor.

package pkg;

import com.microsoft.sqlserver.javalangextension.PrimitiveDataset;
import com.microsoft.sqlserver.javalangextension.AbstractSqlServerExtensionExecutor;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.regex.*;

public class RegexSample extends AbstractSqlServerExtensionExecutor {
    private Pattern expr;

    public RegexSample() {
        // Setup the expected extension version, and class to use for input and output dataset
        executorExtensionVersion = SQLSERVER_JAVA_LANG_EXTENSION_V1;
        executorInputDatasetClassName = PrimitiveDataset.class.getName();
        executorOutputDatasetClassName = PrimitiveDataset.class.getName();
    }

    public PrimitiveDataset execute(PrimitiveDataset input, LinkedHashMap<String, Object> params) {
        // Validate the input parameters and input column schema
        validateInput(input, params);

        int[] inIds = input.getIntColumn(0);
        String[] inValues = input.getStringColumn(1);
        int rowCount = inValues.length;

        String regexExpr = (String)params.get("regexExpr");
        expr = Pattern.compile(regexExpr);

        System.out.println("regex expression: " + regexExpr);

        // Lists to store the output data
        LinkedList<Integer> outIds = new LinkedList<Integer>();
        LinkedList<String> outValues = new LinkedList<String>();

        // Evaluate each row
        for(int i = 0; i < rowCount; i++) {
            if (check(inValues[i])) {
                outIds.add(inIds[i]);
                outValues.add(inValues[i]);
            }
        }

        int outputRowCount = outValues.size();

        int[] idOutputCol = new int[outputRowCount];
        String[] valueOutputCol = new String[outputRowCount];

        // Convert the list of output columns to arrays
        outValues.toArray(valueOutputCol);

        ListIterator<Integer> it = outIds.listIterator(0);
        int rowId = 0;

        System.out.println("Output data:");
        while (it.hasNext()) {
            idOutputCol[rowId] = it.next().intValue();

            System.out.println("ID: " + idOutputCol[rowId] + " Value: " + valueOutputCol[rowId]);
            rowId++;
        }

        // Construct the output dataset
        PrimitiveDataset output = new PrimitiveDataset();

        output.addColumnMetadata(0, "ID", java.sql.Types.INTEGER, 0, 0);
        output.addColumnMetadata(1, "Text", java.sql.Types.NVARCHAR, 0, 0);

        output.addIntColumn(0, idOutputCol, null);
        output.addStringColumn(1, valueOutputCol);

        return output;
    }

    private void validateInput(PrimitiveDataset input, LinkedHashMap<String, Object> params) {
        // Check for the regex expression input parameter
        if (params.get("regexExpr") == null) {
            throw new IllegalArgumentException("Input parameter 'regexExpr' is not found");
        }

        // The expected input schema should be at least 2 columns, (INTEGER, STRING)
        if (input.getColumnCount() < 2) {
            throw new IllegalArgumentException("Unexpected input schema, schema should be an (INTEGER, NVARCHAR or VARCHAR)");
        }

        // Check that the input column types are expected
        if (input.getColumnType(0) != java.sql.Types.INTEGER &&
                (input.getColumnType(1) != java.sql.Types.VARCHAR && input.getColumnType(1) == java.sql.Types.NVARCHAR )) {
            throw new IllegalArgumentException("Unexpected input schema, schema should be an (INTEGER, NVARCHAR or VARCHAR)");
        }
    }

    private boolean check(String text) {
        Matcher m = expr.matcher(text);

        return m.find();
    }
}

.jar dosyası derleme ve oluşturma

Sınıflarınızı ve bağımlılıklarınızı bir .jar dosyaya paketle. Çoğu Java IDE'si (örneğin Eclipse veya IntelliJ), projeyi derlerken veya derlerken dosya oluşturmayı .jar destekler. Dosyasını regex.jarolarak adlandırın.jar.

Java IDE kullanmıyorsanız el ile dosya .jar oluşturabilirsiniz. Daha fazla bilgi için bkz. Sınıf dosyalarından Java .jar dosyası oluşturma.

Uyarı

Bu öğreticide paketler kullanılır. Sınıfın package pkg; en üstündeki satır, derlenen kodun adlı pkgbir alt klasöre kaydedilmesini sağlar. IDE kullanıyorsanız derlenen kod otomatik olarak bu klasöre kaydedilir. Sınıfları el ile derlemek için kullanırsanız javac , derlenmiş kodu klasöre pkg yerleştirmeniz gerekir.

Dış dil oluşturma

Veritabanında bir dış dil oluşturmanız gerekir. Dış dil, veritabanı kapsamlı bir nesnedir. Bu, Java gibi dış dillerin, kullanmak istediğiniz her veritabanı için oluşturulması gerektiği anlamına gelir.

Windows'da dış dil oluşturma

Windows kullanıyorsanız Java için bir dış dil oluşturmak için bu adımları izleyin.

  1. Uzantıyı içeren bir .zip dosyası oluşturun.

    Windows'da SQL Server kurulumunun bir parçası olarak, Java uzantısı .zip dosyası şu konuma yüklenir: [SQL Server install path]\MSSQL\Binn\java-lang-extension.zip. Bu zip dosyası dosyasını javaextension.dlliçerir.

  2. .zip dosyasından bir dış dil Java'sı oluşturun:

    CREATE EXTERNAL LANGUAGE Java
    FROM
    (CONTENT = N'[SQL Server install path]\MSSQL\Binn\java-lang-extension.zip', FILE_NAME = 'javaextension.dll',
    ENVIRONMENT_VARIABLES = N'{"JRE_HOME":"<path to JRE>"}' );
    GO
    

Linux'ta dış dil oluşturma

Kurulumun bir parçası olarak, uzantı .tar.gz dosyası şu yol altına kaydedilir: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz.

Bir dış dil Java'sı oluşturmak için Linux'ta aşağıdaki T-SQL deyimini çalıştırın:

CREATE EXTERNAL LANGUAGE Java
FROM (CONTENT = N'/opt/mssql-extensibility/lib/java-lang-extension.tar.gz', file_name = 'javaextension.so',
ENVIRONMENT_VARIABLES = N'{"JRE_HOME":"<path to JRE>"}' );
GO

Dış dil yürütme izinleri

Java kodunu yürütmek için kullanıcıya bu dilde dış betik yürütme izni verilmesi gerekir.

Daha fazla bilgi için bkz. CREATE EXTERNAL LANGUAGE.

Dış kitaplıklar oluşturma

Dosyalarınız .jar için bir dış kitaplık oluşturmak için CREATE EXTERNAL LIBRARY kullanın. SQL Server'ın dosyalara .jar erişimi vardır ve için özel izinler classpathayarlamanız gerekmez.

Bu örnekte iki dış kitaplık oluşturacaksınız. Biri SDK için, diğeri de RegEx Java kodu için.

  1. SDK jar dosyası mssql-java-lang-extension.jar , SQL Server 2019 (15.x) ve sonraki sürümlerin bir parçası olarak hem Windows hem de Linux'a yüklenir.

    • Windows'ta varsayılan yükleme yolu: <instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jar

    • Linux'ta varsayılan yükleme yolu: /opt/mssql/lib/mssql-java-lang-extension.jar

    Kod ayrıca açık kaynaklıdır ve SQL Server Dil Uzantıları GitHub deposunda bulunabilir. Daha fazla bilgi için bkz. SQL Server için Java için Microsoft Genişletilebilirlik SDK'sı.

  2. SDK için bir dış kitaplık oluşturun.

    CREATE EXTERNAL LIBRARY sdk
    FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar')
    WITH (LANGUAGE = 'Java');
    GO
    
  3. RegEx kodu için bir dış kitaplık oluşturun.

    CREATE EXTERNAL LIBRARY regex
    FROM (CONTENT = '<path>/regex.jar')
    WITH (LANGUAGE = 'Java');
    GO
    

İzinleri ayarlama

Uyarı

Önceki adımda dış kitaplıklar kullanıyorsanız bu adımı atlayın. Önerilen yol, dosyanızdan .jar bir dış kitaplık oluşturmaktır.

Dış kitaplıkları kullanmak istemiyorsanız, gerekli izinleri ayarlamanız gerekir. Betik yürütme yalnızca işlem kimliklerinin kodunuz için erişimi varsa başarılı olur. İzinleri ayarlama hakkında daha fazla bilgiyi yükleme kılavuzunda bulabilirsiniz.

Linux'ta

Kullanıcıya sınıf yolu mssql_satellite üzerinde okuma/yürütme izinleri verin.

Windows'da

Derlenmiş Java kodunuzu içeren klasörde SQLRUserGroup ve Tüm uygulama paketleri SID'sine 'Okuma ve Yürütme' izinleri verin.

Kök üst öğeden son alt klasöre kadar tüm ağacın izinleri olmalıdır.

  1. Klasöre (örneğin, C:\myJavaCode) sağ tıklayın ve Özellikler Güvenliği'ni> seçin.
  2. Düzenle'yi seçin.
  3. Add (Ekle) seçeneğini belirleyin.
  4. Kullanıcıları, Bilgisayarı, Hizmet Hesaplarını veya Grupları Seçin bölümünde:
    1. Nesne Türleri'ne tıklayın ve Yerleşik güvenlik ilkeleri ve Grupları'nın seçili olduğundan emin olun.
    2. Listenin en üstündeki yerel bilgisayar adını seçmek için Konumlar'ı seçin.
  5. SQLRUserGroup girin, adı denetleyin ve tamam'ı seçerek grubu ekleyin.
  6. TÜM UYGULAMA PAKETLERİ girin, adı denetleyin ve eklemek için Tamam'ı seçin. Ad çözümlenmezse Konumlar adımını yeniden ziyaret edin. SID, makinenizde yereldir.

Her iki güvenlik kimliklerinin de klasörde ve alt klasörde Okuma vepkg Yürütme izinlerine sahip olduğundan emin olun.

Java sınıfını çağırma

SQL Server'dan Java kodunu çağırmak için çağıran sp_execute_external_script bir saklı yordam oluşturun. parametresinde script , çağırmak istediğiniz öğesini package.class tanımlayın. Aşağıdaki kodda, sınıfı adlı bir pakete ve adlı pkgRegexSample.javabir sınıf dosyasına aittir.

Uyarı

Kod, çağrılacak yöntemi tanımlamıyor. Varsayılan olarak yöntemi execute çağrılır. Bu, SıNıFı SQL Server'dan çağırabilmek istiyorsanız SDK arabirimini izlemeniz ve Java sınıfınızda bir yürütme yöntemi uygulamanız gerektiği anlamına gelir.

Saklı yordam bir giriş sorgusu (giriş veri kümesi) ve bir normal ifade alır ve verilen normal ifadeyi karşılayan satırları döndürür. Bir metnin veya javasözcüğünü Java içerip içermediğini denetleen normal bir ifade [Jj]ava kullanır.

CREATE OR ALTER PROCEDURE [dbo].[java_regex] (
    @expr NVARCHAR (200),
    @query NVARCHAR (400)
)
AS
BEGIN
    --Call the Java program by giving the package.className in @script
    --The method invoked in the Java code is always the "execute" method
    EXECUTE sp_execute_external_script
        @language = N'Java',
        @script = N'pkg.RegexSample',
        @input_data_1 = @query,
        @params = N'@regexExpr nvarchar(200)',
        @regexExpr = @expr
        WITH RESULT SETS
    (
            (ID INT, TEXT NVARCHAR (100))
    );
END
GO

--Now execute the above stored procedure and provide the regular expression and an input query
EXECUTE [dbo].[java_regex] N'[Jj]ava', N'SELECT id, text FROM testdata';
GO

Results

Çağrıyı yürütürken, iki satır içeren bir sonuç kümesi almanız gerekir.

Java örneğinden alınan sonuçların ekran görüntüsü.

Hata alırsanız

  • Sınıflarınızı derlerken, pkg alt klasör üç sınıfın da derlenmiş kodunu içermelidir.

  • Dış kitaplıklar kullanmıyorsanız, dış işlemi çalıştıran güvenlik kimliklerinin kodunuzu okuma ve yürütme iznine sahip olduğundan emin olmak için herrootpkg klasörden alt klasöre izinleri denetleyin.