Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Область применения: SQL Server 2019 (15.x) и более поздних версий
В этом руководстве показано, как использовать расширения языка SQL Server и создать класс Java, принимающий два столбца (идентификатор и текст) из SQL Server и регулярное выражение (regex) в качестве входного параметра. Класс возвращает в SQL Server два столбца (идентификатор и текст).
Для заданного текста в текстовом столбце, отправленном в класс Java, код проверяет, выполнено ли данное регулярное выражение, и возвращает этот текст вместе с исходным идентификатором.
В этом примере кода используется регулярное выражение, которое проверяет, содержит ли текст слово Java или java.
Предварительные требования
экземпляр компонента ядро СУБД в SQL Server 2019 (15.x) и более поздних версиях с платформой расширяемости и расширением для программирования на Java в Windows или в Linux. Дополнительные сведения см. в разделе "Расширения языка SQL Server". Дополнительные сведения о требованиях к написанию кода см. в статье о вызове среды выполнения Java в расширениях языка SQL Server.
Клиент базы данных. Вы можете подключиться к экземпляру SQL Server с помощью любого знакомого клиентского средства SQL Server, например sqlcmd, SQL Server Management Studio (SSMS) или расширения MSSQL для Visual Studio Code.
Пакет SDK для Java SE (JDK) 8 или JRE 8 в Windows или Linux.
Файл
mssql-java-lang-extension.jarиз пакета SDK расширяемости Майкрософт для Java для SQL Server .
Для этого руководства достаточно компиляции из командной строки с помощью javac.
Создание примера набора данных
Сначала создайте новую базу данных и заполните таблицу testdata столбцами ID и text.
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
Создание основного класса
На этом шаге создайте файл класса с именем RegexSample.java и скопируйте следующий код Java в этот файл.
Этот основной класс импортирует пакет SDK — это значит, что JAR-файл, скачанный в шаге 1, должен быть доступен для обнаружения из этого класса.
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-файла
Упакуйте классы и зависимости в файлы .jar. Большинство IDE Java (например, Eclipse или IntelliJ) поддерживают создание файлов .jar при сборке или компиляции проекта. Присвойте файлу .jarregex.jarимя.
Если вы не используете интегрированную среду разработки Java, можно создать .jar файл вручную. Дополнительные сведения см. в статье "Создание файла java .jar из файлов классов".
Примечание.
В этом учебнике используются пакеты. Строка package pkg; в верхней части класса гарантирует, что скомпилированный код сохраняется в вложенной папке pkg. Если используется IDE, скомпилированный код автоматически сохраняется в этой папке. Если вы используете javac для ручной компиляции классов, необходимо поместить скомпилированный код в папку pkg .
Создание внешнего языка
Необходимо создать внешний язык в базе данных. Внешний язык — это объект области базы данных. Это значит, что внешние языки, такие как Java, необходимо создавать для каждой базы данных, в которой вы хотите их использовать.
Создание внешнего языка в Windows
Если вы используете Windows, выполните следующие действия, чтобы создать внешний язык для Java.
Создайте ZIP-файл, содержащий расширение.
В рамках установки SQL Server в Windows файл расширения
.zipJava устанавливается в этом расположении:[SQL Server install path]\MSSQL\Binn\java-lang-extension.zipЭтот ZIP-файл содержит файлjavaextension.dll.Создайте внешний язык Java из ZIP-файла:
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
В рамках установки файл расширения .tar.gz сохраняется по следующему пути: /opt/mssql-extensibility/lib/java-lang-extension.tar.gz
Чтобы создать внешний язык Java, выполните в Linux следующую инструкцию T-SQL:
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
Разрешения на выполнение внешнего языка
Для выполнения кода Java пользователю необходимо предоставить разрешение на выполнение внешнего скрипта на этом языке.
Дополнительные сведения см. в разделе CREATE EXTERNAL LANGUAGE.
Создание внешних библиотек
Используйте CREATE EXTERNAL LIBRARY, чтобы создать внешнюю библиотеку для файлов .jar. SQL Server имеет доступ к .jar файлам, и вам не нужно задавать специальные разрешения classpath.
В этом примере вы создадите две внешние библиотеки. одна для SDK, вторая для кода Java для RegEx.
Jar-файл
mssql-java-lang-extension.jarпакета SDK устанавливается как часть SQL Server 2019 (15.x) и более поздних версий в Windows и Linux.Путь установки по умолчанию в Windows:
<instance installation home directory>\MSSQL\Binn\mssql-java-lang-extension.jarПуть установки по умолчанию в Linux:
/opt/mssql/lib/mssql-java-lang-extension.jar
Это открытый код, который можно найти в репозитории расширений языка SQL Server в GitHub. Дополнительные сведения см. в разделе Microsoft Extensibility SDK for Java для SQL Server.
Создайте внешнюю библиотеку для пакета SDK.
CREATE EXTERNAL LIBRARY sdk FROM (CONTENT = '<OS specific path from above>/mssql-java-lang-extension.jar') WITH (LANGUAGE = 'Java'); GOСоздайте внешнюю библиотеку для кода RegEx.
CREATE EXTERNAL LIBRARY regex FROM (CONTENT = '<path>/regex.jar') WITH (LANGUAGE = 'Java'); GO
Настройка разрешений
Примечание.
Пропустите этот шаг, если на предыдущем этапе вы использовали внешние библиотеки. Рекомендуемый способ — создать внешнюю библиотеку из файла .jar.
Если вы не хотите использовать внешние библиотеки, необходимо задать необходимые разрешения. Выполнение скрипта возможно только в том случае, если учетные записи процессов имеют доступ к вашему коду. Дополнительные сведения о настройке разрешений см. в руководстве по установке.
На Linux
Предоставьте пользователю mssql_satellite права на чтение и выполнение для classpath.
В Windows
Предоставьте права на чтение и выполнение для SQLRUserGroup и SID Все пакеты приложений для папки, содержащей скомпилированный код Java.
Для всех каталогов в дереве — от корневого каталога до последней вложенной папки — должны быть настроены права доступа.
- Щелкните папку (например,
C:\myJavaCode) правой кнопкой мыши и выберите Свойства>Безопасность. - Выберите Изменить.
- Выберите Добавить.
- В разделе "Выбор пользователей", "Компьютер", "Учетные записи службы" или "Группы":
- Выберите типы объектов и убедитесь, что выбраны встроенные принципы безопасности и группы .
- Выберите расположения , чтобы выбрать имя локального компьютера в верхней части списка.
- Введите SQLRUserGroup, проверьте имя и нажмите кнопку "ОК ", чтобы добавить группу.
- Введите ВСЕ ПАКЕТЫ ПРИЛОЖЕНИЙ, проверьте имя и нажмите кнопку ОК, чтобы добавить запись. Если имя разрешить не удается, верните к шагу "Расположения". Идентификатор безопасности является локальным для вашего компьютера.
Убедитесь, что оба субъекта безопасности имеют права "Чтение и выполнение" для папки и подпапки pkg.
Вызов класса Java
Создайте хранимую процедуру, которая вызывает sp_execute_external_script для вызова кода Java из SQL Server. В параметре script укажите, какой package.class требуется вызвать. В следующем коде класс принадлежит пакету с именем pkg и файлу класса с именем RegexSample.java.
Примечание.
Код не определяет, какой метод следует вызывать. По умолчанию метод execute вызывается. В связи с этим, чтобы иметь возможность вызывать класс из SQL Server, вам нужно следовать интерфейсу SDK и реализовать метод execute в классе Java.
Хранимая процедура принимает входной запрос (входной набор данных) и регулярное выражение и возвращает строки, которые выполнили данное регулярное выражение. Он использует регулярное выражение [Jj]ava , которое проверяет, содержит ли текст слово Java или java.
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
Результаты
После выполнения вызова вы должны получить набор результатов из двух строк.
Если возникла ошибка
При компиляции классов вложенная
pkgпапка должна содержать скомпилированный код для всех трех классов.Если вы не используете внешние библиотеки, проверьте права доступа к каждой папке, от
rootдо вложенной папкиpkg, чтобы убедиться, что субъекты безопасности, от имени которых выполняется внешний процесс, имеют разрешение на чтение и выполнение вашего кода.