Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Табличные параметры обеспечивают простой способ передавать несколько строк данных из клиентского приложения в SQL Server без необходимости выполнять многократные обращения к серверу или использовать специальную серверную логику для её обработки. Параметры, возвращающие табличное значение, можно использовать для инкапсуляции строк данных в клиентском приложении и их отправки на сервер единой параметризованной командой. Входящие строки данных хранятся в переменной таблицы, которой затем можно управлять с помощью Transact-SQL.
Доступ к значениям столбца в возвращающих табличное значение параметрах обеспечивается с помощью стандартных инструкций Transact-SQL SELECT. Параметры табличного типа строго типизированы, и их структура автоматически проверяется. Размер возвращающих табличное значение параметров ограничен только объемом памяти сервера.
Примечание.
Поддержка возвращающих табличное значение параметров доступна, начиная с Microsoft JDBC Driver 6.0 для SQL Server.
В параметре, возвращающем табличное значение, невозможно вернуть данные. Параметры, имеющие табличное значение, используются только для ввода; ключевое слово OUTPUT не поддерживается.
Дополнительные сведения о табличнозначных параметрах см. в следующих ресурсах.
| Ресурс | Описание |
|---|---|
| Возвращающие табличное значение параметры (ядро СУБД) в электронной документации на SQL Server | Описывает создание и использование табличных параметров. |
| Определяемые пользователем табличные типы в электронной документации на SQL Server | Описывает пользовательские табличные типы, используемые для объявления параметров табличного типа. |
Передача нескольких строк данных в предыдущих версиях SQL Server
До появления в SQL Server 2008 параметров, возвращающих табличное значение, были ограниченны возможности передачи нескольких строк данных в хранимую процедуру или параметризованную команду SQL. Разработчик может выбрать один из следующих вариантов передачи нескольких строк на сервер.
Использовать ряд отдельных параметров, чтобы представить значения в нескольких столбцах и строках данных. Объем данных, которые можно передать с помощью этого метода, ограничен количеством допустимых параметров. В процедурах SQL Server можно использовать не более 2100 параметров. Для сборки этих отдельных значений в табличную переменную или временную таблицу для обработки требуется логика на стороне сервера.
Объединить несколько значений данных в строки с разделителями или документы XML, а затем передать эти текстовые значения в процедуру или инструкцию. Для этого требуется, чтобы процедура или инструкция содержали логику, необходимую для проверки структур данных и разъединения значений.
Создать ряд отдельных инструкций SQL для изменений данных, затрагивающих несколько строк. Изменения можно отправлять на сервер по отдельности или объединять в группы. Тем не менее даже при отправке в пакетах, содержащих несколько инструкций, каждая из них выполняется на сервере отдельно.
Используйте служебную программу bcp или SQLServerBulkCopy, чтобы загрузить в таблицу большое количество строк. Хотя этот метод эффективен, он не поддерживает обработку на стороне сервера, если данные не загружены во временную таблицу или табличную переменную.
Создание типов табличных параметров
Параметры табличного типа основаны на строго типизированных табличных структурах, которые определяются с помощью инструкций Transact-SQL CREATE TYPE. Прежде чем использовать в клиентских приложениях параметры, имеющие табличное значение, необходимо создать в SQL Server табличный тип и определить его структуру. Дополнительные сведения о создании типов таблиц см. в разделе Определяемые пользователем табличные типы электронной документации на SQL Server.
CREATE TYPE dbo.CategoryTableType AS TABLE
( CategoryID int, CategoryName nvarchar(50) )
После создания табличного типа можно объявить параметры, имеющие табличное значение, на основе этого типа. В приведенном ниже фрагменте кода Transact-SQL демонстрируется объявление возвращающего табличное значение параметра в определении хранимой процедуры. Для объявления параметра с табличным значением требуется ключевое слово READONLY.
CREATE PROCEDURE usp_UpdateCategories
(@tvpNewCategories dbo.CategoryTableType READONLY)
Изменение данных с использованием табличных параметров (Transact-SQL)
Параметры табличного типа можно использовать в операциях модификации данных на основе наборов, затрагивающих несколько строк, при выполнении одного оператора. Например, можно выбрать в возвращающем табличное значение параметре все строки и вставить их в таблицу базы данных. Кроме того, можно создать инструкцию UPDATE, присоединив возвращающий табличное значение параметр к таблице, которую необходимо обновить.
В следующей Transact-SQL UPDATE инструкции показано, как использовать табличный параметр, присоединив его к таблице "Категории". При использовании возвращающего табличное значение параметра со значением JOIN в предложении FROM необходимо также присвоить ему псевдоним, как показано здесь, где параметр с табличным значением имеет псевдоним "ec":
UPDATE dbo.Categories
SET Categories.CategoryName = ec.CategoryName
FROM dbo.Categories INNER JOIN @tvpEditedCategories AS ec
ON dbo.Categories.CategoryID = ec.CategoryID;
В этом примере Transact-SQL показано, как выбрать строки из табличного параметра для выполнения INSERT в рамках одной операции над набором.
INSERT INTO dbo.Categories (CategoryID, CategoryName)
SELECT nc.CategoryID, nc.CategoryName FROM @tvpNewCategories AS nc;
Ограничения табличных параметров
У табличных параметров есть несколько ограничений:
Параметры табличного типа нельзя передавать пользовательским функциям.
Для табличных параметров можно создавать индексы только для поддержки ограничений UNIQUE или PRIMARY KEY. SQL Server не поддерживает статистику для параметров табличного типа.
В коде Transact-SQL возвращающие табличное значение параметры предназначены только для чтения. Нельзя обновлять значения столбцов в строках табличного параметра, а также вставлять или удалять строки. Чтобы изменить данные, передаваемые в хранимую процедуру или параметризованное выражение через табличный параметр, необходимо вставить их во временную таблицу или в табличную переменную.
Нельзя использовать инструкции ALTER TABLE для изменения структуры параметров с табличным значением.
В параметре с табличным значением можно передавать большие объекты в потоковом режиме.
Настройка табличного параметра
Начиная с Microsoft JDBC Driver 6.0 для SQL Server, табличнозначные параметры поддерживаются в параметризованном операторе или параметризованной хранимой процедуре. Параметры табличного типа можно заполнить из SQLServerDataTable, из ResultSet или из предоставленной пользователем реализации интерфейса ISQLServerDataRecord. При задании параметра табличного типа для подготовленного запроса необходимо указать имя типа, которое должно совпадать с именем совместимого типа, ранее созданного на сервере.
В следующих двух фрагментах кода показано, как настроить параметр табличного типа с помощью SQLServerPreparedStatement и SQLServerCallableStatement для вставки данных. Здесь объект sourceTVPObject может быть объектом SQLServerDataTable, результирующим набором или объектом ISQLServerDataRecord. В примерах предполагается, что подключение является активным объектом Connection.
// Using table-valued parameter with a SQLServerPreparedStatement.
SQLServerPreparedStatement pStmt =
(SQLServerPreparedStatement) connection.prepareStatement("INSERT INTO dbo.Categories SELECT * FROM ?");
pStmt.setStructured(1, "dbo.CategoryTableType", sourceTVPObject);
pStmt.execute();
// Using table-valued parameter with a SQLServerCallableStatement.
SQLServerCallableStatement pStmt =
(SQLServerCallableStatement) connection.prepareCall("exec usp_InsertCategories ?");
pStmt.setStructured(1, "dbo.CategoryTableType", sourceTVPObject);;
pStmt.execute();
Примечание.
Полный список интерфейсов API, доступных для настройки возвращающего табличное значение параметра, см. в разделе API-интерфейс возвращающего табличное значение параметра для драйвера JDBC ниже.
Передача табличного параметра как объекта SQLServerDataTable
Начиная с Microsoft JDBC Driver 6.0 для SQL Server, класс SQLServerDataTable представляет таблицу реляционных данных в памяти. В этом примере показано, как создать возвращающий табличное значение параметр из данных в памяти с помощью объекта SQLServerDataTable. Сначала код создает объект SQLServerDataTable, определяет его схему и заполняет таблицу данными. Затем код настраивает SQLServerPreparedStatement, который передает эту таблицу данных в SQL Server как табличный параметр.
/* Assumes connection is an active Connection object. */
// Create an in-memory data table.
SQLServerDataTable sourceDataTable = new SQLServerDataTable();
// Define metadata for the data table.
sourceDataTable.addColumnMetadata("CategoryID" ,java.sql.Types.INTEGER);
sourceDataTable.addColumnMetadata("CategoryName" ,java.sql.Types.NVARCHAR);
// Populate the data table.
sourceDataTable.addRow(1, "CategoryNameValue1");
sourceDataTable.addRow(2, "CategoryNameValue2");
// Pass the data table as a table-valued parameter using a prepared statement.
SQLServerPreparedStatement pStmt =
(SQLServerPreparedStatement) connection.prepareStatement(
"INSERT INTO dbo.Categories SELECT * FROM ?;");
pStmt.setStructured(1, "dbo.CategoryTableType", sourceDataTable);
pStmt.execute();
Этот пример аналогичен предыдущему. Единственное отличие состоит в том, что он задает имя TVP для SQLServerDataTable вместо того, чтобы полагаться на приведение PreparedStatement к SQLServerPreparedStatement для использования метода setStructured.
/* Assumes connection is an active Connection object. */
// Create an in-memory data table.
SQLServerDataTable sourceDataTable = new SQLServerDataTable();
sourceDataTable.setTvpName("dbo.CategoryTableType");
// Define metadata for the data table.
sourceDataTable.addColumnMetadata("CategoryID" ,java.sql.Types.INTEGER);
sourceDataTable.addColumnMetadata("CategoryName" ,java.sql.Types.NVARCHAR);
// Populate the data table.
sourceDataTable.addRow(1, "CategoryNameValue1");
sourceDataTable.addRow(2, "CategoryNameValue2");
// Pass the data table as a table-valued parameter using a prepared statement.
PreparedStatement pStmt =
connection.prepareStatement(
"INSERT INTO dbo.Categories SELECT * FROM ?;");
pStmt.setObject(1, sourceDataTable);
pStmt.execute();
Примечание.
Полный список интерфейсов API, доступных для настройки возвращающего табличное значение параметра, см. в разделе API-интерфейс возвращающего табличное значение параметра для драйвера JDBC ниже.
Передача табличного параметра в виде объекта ResultSet
В этом примере показано, как выполнять потоковую передачу строк данных из ResultSet в табличный параметр. Сначала код извлекает данные из исходной таблицы, создает объект SQLServerDataTable, определяет его схему и заполняет таблицу данными. Затем код настраивает SQLServerPreparedStatement для передачи этой таблицы данных в SQL Server в качестве табличного параметра.
/* Assumes connection is an active Connection object. */
// Create the source ResultSet object. Here SourceCategories is a table defined with the same schema as Categories table.
ResultSet sourceResultSet = connection.createStatement().executeQuery("SELECT * FROM SourceCategories");
// Pass the source result set as a table-valued parameter using a prepared statement.
SQLServerPreparedStatement pStmt =
(SQLServerPreparedStatement) connection.prepareStatement(
"INSERT INTO dbo.Categories SELECT * FROM ?;");
pStmt.setStructured(1, "dbo.CategoryTableType", sourceResultSet);
pStmt.execute();
Примечание.
Полный список интерфейсов API, доступных для настройки возвращающего табличное значение параметра, см. в разделе API-интерфейс возвращающего табличное значение параметра для драйвера JDBC ниже.
Передача параметра табличного типа как объекта ISQLServerDataRecord
Начиная с Microsoft JDBC Driver 6.0 для SQL Server, доступен новый интерфейс ISQLServerDataRecord для потоковой передачи данных с использованием табличного параметра (в зависимости от того, как пользователь реализует этот интерфейс). В следующем примере показано, как реализовать интерфейс ISQLServerDataRecord и передать его в качестве возвращающего табличное значение параметра. Для простоты в следующем примере в параметр табличного типа передается только одна строка с жестко заданными значениями. В идеале пользователь будет реализовывать этот интерфейс для потоковой передачи строк из любого источника, например из текстовых файлов.
class MyRecords implements ISQLServerDataRecord
{
int currentRow = 0;
Object[] row = new Object[2];
MyRecords(){
// Constructor. This implementation has just one row.
row[0] = new Integer(1);
row[1] = "categoryName1";
}
public int getColumnCount(){
// Return the total number of columns, for this example it is 2.
return 2;
}
public SQLServerMetaData getColumnMetaData(int columnIndex) {
// Return the column metadata.
if (1 == columnIndex)
return new SQLServerMetaData("CategoryID", java.sql.Types.INTEGER);
else
return new SQLServerMetaData("CategoryName", java.sql.Types.NVARCHAR);
}
public Object[] getRowData(){
// Return the columns in the current row as an array of objects. This implementation has just one row.
return row;
}
public boolean next(){
// Move to the next row. This implementation has just one row, after processing the first row, return false.
currentRow++;
if (1 == currentRow)
return true;
else
return false;
}
}
// Following code demonstrates how to pass MyRecords object as a table-valued parameter.
MyRecords sourceRecords = new MyRecords();
SQLServerPreparedStatement pStmt =
(SQLServerPreparedStatement) connection.prepareStatement(
"INSERT INTO dbo.Categories SELECT * FROM ?;");
pStmt.setStructured(1, "dbo.CategoryTableType", sourceRecords);
pStmt.execute();
Примечание.
Полный список интерфейсов API, доступных для настройки возвращающего табличное значение параметра, см. в разделе API-интерфейс возвращающего табличное значение параметра для драйвера JDBC ниже.
API параметров табличного типа для драйвера JDBC
SQLServerMetaData
Этот класс представляет метаданные для столбца. Он используется в интерфейсе ISQLServerDataRecord для передачи метаданных столбцов табличному параметру. В этом классе используются следующие методы.
| Имя | Описание |
|---|---|
| public SQLServerMetaData(String имяСтолбца, int типSQL, int точность, int масштаб, boolean использоватьСерверПоУмолчанию, boolean уникальныйКлюч, SQLServerSortOrder порядокСортировки, int индексСортировки) | Инициализирует новый экземпляр SQLServerMetaData с указанным именем столбца, типом SQL, точностью, масштабом и сервером по умолчанию. Эта форма конструктора поддерживает табличные параметры и позволяет указать, является ли столбец в табличном параметре уникальным, а также порядок сортировки столбца и порядковый номер столбца сортировки. Объект useServerDefault — указывает, должно ли в этом столбце использоваться значение сервера по умолчанию. Значение по умолчанию — false. isUniqueKey — указывает, является ли столбец в параметре табличного типа уникальным; значение по умолчанию — false. sortOrder — указывает порядок сортировки для столбца; значение по умолчанию — SQLServerSortOrder.Unspecified. Объект sortOrdinal — указывает порядковый номер столбца сортировки. Значения sortOrdinal начинаются с 0. Значение по умолчанию: −1. |
| public SQLServerMetaData(String columnName, int sqlType) | Инициализирует новый экземпляр SQLServerMetaData, используя имя столбца и тип SQL. |
| public SQLServerMetaData(String columnName, int sqlType, int length) | Инициализирует новый экземпляр SQLServerMetaData, используя имя столбца, тип SQL и длину (для строковых данных). Длина используется для различения больших строк и строк длиной менее 4000 символов. Этот метод представлен в версии 7.2 драйвера JDBC. |
| public SQLServerMetaData(String columnName, int sqlType, int precision, int scale) | Инициализирует новый экземпляр SQLServerMetaData, используя имя столбца, тип SQL, точность и масштаб. |
| Public SQLServerMetaData(SQLServerMetaData sqlServerMetaData) | Инициализирует новый экземпляр класса SQLServerMetaData из другого объекта SQLServerMetaData. |
| public String getColumName() | Возвращает имя столбца. |
| public int getSqlType() | Извлекает тип Java SQL. |
| public int getPrecision() | Возвращает точность типа, переданного для столбца. |
| public int getScale() | Извлекает масштаб типа, переданного в столбец. |
| public SQLServerSortOrder getSortOrder() | Извлекает порядок сортировки. |
| public int getSortOrdinal() | Возвращает порядковый номер сортировки. |
| public boolean isUniqueKey() | Извлекает значение, указывающее, является ли столбец уникальным. |
| public boolean useServerDefault() | Возвращает значение, указывающее, использует ли столбец значение сервера по умолчанию. |
SQLServerSortOrder
Перечисление, определяющее порядок сортировки. Возможные значения: По возрастанию, По убыванию и Не указано.
SQLServerDataTable
Этот класс представляет собой таблицу данных в памяти, используемую с параметрами табличного типа. В этом классе используются следующие методы.
| Имя | Описание |
|---|---|
| Public SQLServerDataTable() | Инициализирует новый экземпляр SQLServerDataTable. |
| public Iterator Entry<Integer, Object[]< getIterator>>() | Извлекает итератор в строках таблицы данных. |
| public void addColumnMetadata(String columnName, int sqlType) | Добавляет метаданные для указанного столбца. |
| public void addColumnMetadata(столбец SQLServerDataColumn) | Добавляет метаданные для указанного столбца. |
| public void addRow(Object... значения) | Добавляет одну строку данных в таблицу данных. |
| public Map<Integer, SQLServerDataColumn> getColumnMetadata() | Извлекает метаданные столбца этой таблицы данных. |
| public void очистить() | Очищает эту таблицу данных. |
SQLServerDataColumn
Этот класс представляет столбец таблицы данных в памяти, представленный SQLServerDataTable. В этом классе используются следующие методы.
| Имя | Описание |
|---|---|
| public SQLServerDataColumn(String columnName, int sqlType) | Инициализирует новый экземпляр SQLServerDataColumn с именем и типом столбца. |
| public String getColumnName() | Возвращает имя столбца. |
| public int getColumnType() // возвращает тип столбца | Извлекает тип столбца. |
ISQLServerDataRecord
Этот класс представляет интерфейс, который пользователи могут реализовать для потоковой передачи данных в табличнозначный параметр. В этом интерфейсе используются следующие методы.
| Имя | Описание |
|---|---|
| public SQLServerMetaData getColumnMetaData(int column); | Извлекает метаданные столбца по указанному индексу. |
| public int getColumnCount(); | Извлекает общее число столбцов. |
| public Object[] getRowData(); | Получает данные для текущей строки как массив объектов. |
| public boolean next(); | Переходит к следующей строке. Возвращает значение true, если перемещение выполнено успешно и имеется наведенная дальше строка. В противном случае возвращает значение false. |
SQLServerPreparedStatement
Для поддержки передачи параметров табличного типа в этот класс были добавлены следующие методы.
| Имя | Описание |
|---|---|
| public final void setStructured(int parameterIndex, String tvpName, SQLServerDataTable tvpDataTable) | Заполняет параметр табличного типа таблицей данных. parameterIndex — индекс параметра, tvpName — имя табличного параметра, а tvpDataTable — объект исходной таблицы данных. |
| public final void setStructured(int parameterIndex, String tvpName, ResultSet tvpResultSet) | Заполняет параметр табличного типа данными из ResultSet, полученного из другой таблицы. parameterIndex — индекс параметра, tvpName — имя параметра табличного типа, а tvpResultSet — объект исходного набора результатов. |
| public final void setStructured(int parameterIndex, String tvpName, ISQLServerDataRecord tvpDataRecord) | Заполняет параметр табличного типа объектом ISQLServerDataRecord. ISQLServerDataRecord используется для потоковой передачи данных, и пользователь решает, как его использовать. parameterIndex — номер параметра, tvpName — имя табличного параметра, а tvpDataRecord — объект ISQLServerDataRecord. |
SQLServerCallableStatement
В этот класс были добавлены следующие методы для поддержки передачи параметров табличного типа.
| Имя | Описание |
|---|---|
| public final void setStructured(String parameterName, String tvpName, SQLServerDataTable tvpDataTable) | Заполняет параметр с табличным значением, переданный хранимой процедуре, данными из таблицы данных. parameterName — это имя параметра, tvpName — это имя типа TVP, а tvpDataTable — объект таблицы данных. |
| public final void setStructured(String parameterName, String tvpName, ResultSet tvpResultSet) | Заполняет параметр табличного типа, переданный в хранимую процедуру, данными из набора результатов, полученного из другой таблицы. parameterName — это имя параметра, tvpName — это имя типа TVP, а tvpResultSet — это объект исходного результирующего набора. |
| общедоступный окончательный метод void setStructured(String parameterName, String tvpName, ISQLServerDataRecord tvpDataRecord) | Заполняет параметр с табличным значением, переданный в хранимую процедуру, объектом ISQLServerDataRecord. ISQLServerDataRecord используется для потоковой передачи данных, и пользователь решает, как его использовать. parameterName — это имя параметра, tvpName — это имя типа TVP, а tvpDataRecord — это объект ISQLServerDataRecord. |