Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op: SQL Server 2019 (15.x) en latere versies
In deze zelfstudie leert u hoe u SQL Server Language Extensions gebruikt om een Java-klasse te maken die twee kolommen (id en tekst) van SQL Server ontvangt en een reguliere expressie (regex) als invoerparameter. De klasse retourneert twee kolommen terug naar SQL Server (id en tekst).
Voor een bepaalde tekst in de tekstkolom die naar de Java-klasse wordt verzonden, controleert de code of aan de opgegeven reguliere expressie is voldaan en wordt die tekst samen met de oorspronkelijke id geretourneerd.
Deze voorbeeldcode maakt gebruik van een reguliere expressie die controleert of een tekst het woord Java bevat of java.
Vereiste voorwaarden
Database Engine-exemplaar op SQL Server 2019 (15.x) en latere versies, met het uitbreidbaarheidsframework en de Java-programmeerextensie in Windows of linux. Zie SQL Server Language Extensions voor meer informatie. Zie De Java-runtime aanroepen in SQL Server Language Extensions voor meer informatie over coderingsvereisten.
SQL Server Management Studio of Azure Data Studio voor het uitvoeren van T-SQL.
Java SE Development Kit (JDK) 8 of JRE 8 op Windows of Linux.
Het
mssql-java-lang-extension.jarbestand van de Microsoft Extensibility SDK voor Java voor SQL Server .
Compilatie van opdrachtregels is javac voldoende voor deze zelfstudie.
Voorbeeldgegevens maken
Maak eerst een nieuwe database en vul een testdata tabel met ID en text kolommen.
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
De hoofdklasse maken
In deze stap maakt u een klassebestand met de naam RegexSample.java en kopieert u de volgende Java-code naar dat bestand.
Deze hoofdklasse importeert de SDK, wat betekent dat het JAR-bestand dat in stap1 is gedownload, kan worden gedetecteerd vanuit deze klasse.
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();
}
}
Een .jar-bestand compileren en maken
Verpak uw klassen en afhankelijkheden in een .jar bestand. De meeste Java IDE's (bijvoorbeeld Eclipse of IntelliJ) ondersteunen het genereren van .jar bestanden wanneer u het project bouwt of compileert. Geef het bestand regex.jareen .jar naam.
Als u geen Java IDE gebruikt, kunt u handmatig een .jar bestand maken. Zie Een Java-.jar-bestand maken op basis van klassebestanden voor meer informatie.
Opmerking
In deze zelfstudie worden pakketten gebruikt. De package pkg; regel boven aan de klasse zorgt ervoor dat de gecompileerde code wordt opgeslagen in een submap met de naam pkg. Als u een IDE gebruikt, wordt de gecompileerde code automatisch opgeslagen in deze map. Als u javac de klassen handmatig compileert, moet u de gecompileerde code in de pkg map plaatsen.
Externe taal maken
U moet een externe taal maken in de database. De externe taal is een database-scoped object, wat betekent dat externe talen zoals Java moeten worden gemaakt voor elke database waarin u deze wilt gebruiken.
Externe taal maken in Windows
Als u Windows gebruikt, volgt u deze stappen om een externe taal voor Java te maken.
Maak een .zip-bestand met de extensie.
Als onderdeel van de INSTALLATIE van SQL Server in Windows wordt het Java-extensiebestand
.zipop deze locatie geïnstalleerd:[SQL Server install path]\MSSQL\Binn\java-lang-extension.zip. Dit ZIP-bestand bevat dejavaextension.dll.Een externe taal maken in Java op basis van het .zip-bestand:
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
Externe taal maken in Linux
Als onderdeel van de installatie wordt het extensiebestand .tar.gz opgeslagen onder het volgende pad: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz.
Voer de volgende T-SQL-instructie uit op Linux om een externe taal te maken:
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
Machtigingen voor het uitvoeren van een externe taal
Als u Java-code wilt uitvoeren, moet aan een gebruiker externe scriptuitvoering voor die specifieke taal worden verleend.
Zie CREATE EXTERNAL LANGUAGE voor meer informatie.
Externe bibliotheken maken
Gebruik CREATE EXTERNAL LIBRARY om een externe bibliotheek voor uw .jar bestanden te maken. SQL Server heeft toegang tot de .jar bestanden en u hoeft geen speciale machtigingen in te stellen op de classpath.
In dit voorbeeld maakt u twee externe bibliotheken. Eén voor de SDK en één voor de RegEx Java-code.
Het SDK JAR-bestand
mssql-java-lang-extension.jarwordt geïnstalleerd als onderdeel van SQL Server 2019 (15.x) en nieuwere versies, zowel in Windows als Linux.Standaardinstallatiepad in Windows:
<instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jarStandaardinstallatiepad in Linux:
/opt/mssql/lib/mssql-java-lang-extension.jar
De code is ook open source en is te vinden in de GitHub-opslagplaats voor SQL Server Language Extensions. Zie Microsoft Extensibility SDK voor Java voor SQL Server voor meer informatie.
Maak een externe bibliotheek voor de SDK.
CREATE EXTERNAL LIBRARY sdk FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar') WITH (LANGUAGE = 'Java'); GOMaak een externe bibliotheek voor de RegEx-code.
CREATE EXTERNAL LIBRARY regex FROM (CONTENT = '<path>/regex.jar') WITH (LANGUAGE = 'Java'); GO
Machtigingen instellen
Opmerking
Sla deze stap over als u externe bibliotheken in de vorige stap gebruikt. De aanbevolen manier is om een externe bibliotheek te maken op basis van uw .jar bestand.
Als u geen externe bibliotheken wilt gebruiken, moet u de benodigde machtigingen instellen. De uitvoering van het script slaagt alleen als de procesidentiteiten toegang hebben tot uw code. Meer informatie over het instellen van machtigingen vindt u in de installatiehandleiding.
In Linux
Lees-/uitvoermachtigingen verlenen voor het klassepad aan de mssql_satellite gebruiker.
In Windows
Ververleent lees- en uitvoermachtigingen aan SQLRUserGroup en de SID alle toepassingspakketten op de map met uw gecompileerde Java-code.
De hele structuur moet machtigingen hebben, van bovenliggende hoofdmap tot de laatste submap.
- Klik met de rechtermuisknop op de map (bijvoorbeeld
C:\myJavaCode) en kies Eigenschappenbeveiliging>. - Kies Bewerken.
- Selecteer Toevoegen.
-
Selecteer gebruikers, computers, serviceaccounts of groepen:
- Selecteer Objecttypen en zorg ervoor dat ingebouwde beveiligingsprincipes en groepen zijn geselecteerd.
- Selecteer Locaties om de naam van de lokale computer boven aan de lijst te selecteren.
- Voer SQLRUserGroup in, controleer de naam en selecteer OK om de groep toe te voegen.
- Voer ALLE TOEPASSINGSPAKKETTEN in, controleer de naam en selecteer OK om toe te voegen. Als de naam niet wordt omgezet, gaat u opnieuw naar de stap Locaties. De SID is lokaal op uw computer.
Zorg ervoor dat beide beveiligingsidentiteiten lees- en uitvoermachtigingen hebben voor de map en de pkg submap.
De Java-klasse aanroepen
Maak een opgeslagen procedure waarmee de Java-code vanuit SQL Server wordt aangeroepen sp_execute_external_script . Definieer in de script parameter welke package.class u wilt aanroepen. In de volgende code behoort de klasse tot een pakket met de naam pkg en een klassebestand met de naam RegexSample.java.
Opmerking
De code definieert niet welke methode moet worden aangeroepen. Standaard wordt de execute methode aangeroepen. Dit betekent dat u de SDK-interface moet volgen en een uitvoermethode in uw Java-klasse moet implementeren als u de klasse wilt kunnen aanroepen vanuit SQL Server.
De opgeslagen procedure gebruikt een invoerquery (invoergegevensset) en een reguliere expressie en retourneert de rijen die aan de opgegeven reguliere expressie hebben voldaan. Er wordt een reguliere expressie [Jj]ava gebruikt die controleert of een tekst het woord javaJava of .
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
Nadat de aanroep is uitgevoerd, krijgt u een resultatenset met twee van de rijen.
Als u een foutmelding krijgt
Wanneer u uw klassen compileert, moet de
pkgsubmap de gecompileerde code voor alle drie de klassen bevatten.Als u geen externe bibliotheken gebruikt, controleert u de machtigingen voor elke map, van de naar
pkgderootsubmap, om ervoor te zorgen dat de beveiligingsidentiteiten waarop het externe proces wordt uitgevoerd, gemachtigd zijn om uw code te lezen en uit te voeren.