Относительно динамического построения sql

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

когда мы загружаем xml в cursor, мы указываем имя столбца и их тип данных и размер. вместо того, чтобы указывать вручную, как я мог бы сделать эту область динамической. предположим, что мой tsql выглядит следующим образом

 Exec sp_xml_preparedocument @XMLFormat OUTPUT, @DetailXml

-- Create Cursor from XML Table

Declare CurDetailRecord
Cursor For
Select productid,unit,rate,qty,amount
From Openxml (@XMLFormat, '/NewDataSet/PurchaseOrderDetail', 2)
With
(
productid Varchar(10),
unit Varchar(50),
rate decimal(18,2),
qty decimal(18,3),
amount decimal(18,2)
)
  

вот в качестве примера

 productid Varchar(10),
unit Varchar(50) 
  

и т.д. Я указываю, а также указываю тип и размер их данных.

итак, как я мог бы динамически создавать эту область и динамически извлекать имя столбца, тип и размер данных.

пожалуйста, направьте меня, спасибо.

Ответ №1:

Вы можете получить имена столбцов (которые являются узлами внутри узла PurchasePrderDetail) следующим образом:

  declare @xml xml='<NewDataSet><PurchaseOrderDetail>
<productid>19125</productid>
</PurchaseOrderDetail></NewDataSet>'
SELECT b.value('local-name(.)','nvarchar(128)')ColumnName,
    LEN(b.value('.','nvarchar(128)'))MaxLength
 FROM @xml.nodes('/NewDataSet/PurchaseOrderDetail/*') a(b)
  

Таким образом, вы можете сгенерировать динамическую инструкцию SQL для создания курсора с соответствующими именами столбцов и длиной, такими как varchar(MaxLength).

Но вы не можете получить типы данных из XML, не зная реальных имен столбцов, потому что данные в xml — это просто текст, и, например, «5» может быть int типом, а также просто текстом.

Редактировать

Если вы знаете имя таблицы, вы можете создать динамическую инструкцию SQL, используя метаданные из этой таблицы, используя это:

 ; With cols as(
SELECT COLUMN_NAME,
UPPER(DATA_type)
 
case when data_type like  '%char' then 
    case when CHARACTER_MAXIMUM_LENGTH=-1 THEN ' (MAX)'
    else ' (' CAST(CHARACTER_MAXIMUM_LENGTH as nvarchar) ')'
    END
ELSE '' 
END ColConv
 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='PurchaseOrderDetail'),
XMLS as(
SELECT b.value('local-name(.)','nvarchar(128)')ColumnName,
    b.value('.','nvarchar(128)')Value
 FROM @xml.nodes('/NewDataSet/PurchaseOrderDetail/*') a(b)
)
SELECT XMLS.ColumnName,'CAST (''' XMLS.Value ''' AS '  ColConv ''')'  FROM XMLS
JOIN cols ON XMLS.ColumnName=cols.COLUMN_NAME
  

В качестве выходных данных у вас будет имя столбца и значение с соответствующим CAST предложением. Затем вы можете создать динамический оператор, который вам нужен.

Комментарии:

1. существует таблица с именем PurchaseOrderDetail, где определен тот же номер столбца ….. разве мы не можем извлечь тип данных столбца оттуда и динамически сгенерировать целое предложение with, где будут указаны имя столбца, тип данных и размер.

Ответ №2:

Обычно информация о типах данных и именах полей описывается в XSD файле (определение XML-схемы).

Итак, вам нужно иметь действительный XSD-файл для каждого вашего XML-файла, тогда вы сможете получить имя полей и тип данных.

Вот ссылка для лучшего понимания XSD

И вот как шаг за шагом работать с XSD и XML

Надеюсь, это поможет вам

Комментарии:

1. существует таблица с именем PurchaseOrderDetail, где определен тот же номер столбца ….. разве мы не можем извлечь тип данных столбца оттуда и динамически сгенерировать целое предложение with, где будут указаны имя столбца, тип данных и размер.