我已經看到了這個問題
這是我執行 XML 中的命令的方式:
declare @i int = 1
select @sql1 = ''
SELECT @SQL2 = 'Radhe'
WHILE @sql2 is not null
begin
SELECT @sql2 = @XML.value('(/Krishna/text())[sql:variable("@i") cast as xs:int?][1]', 'varchar(max)')
if @DEBUG=1
PRINT COALESCE(@sql2,'@SQL2 WAS NULL' ' -- @I IS ' CAST(@I AS VARCHAR(5)))
if @sql2 is not null
begin
SET @sql1 = CAST (@sql1 @sql2 @vbCrLf AS NVARCHAR(MAX))
IF @PrintOnly = 1
BEGIN
EXEC sp_DisplayNVarchar @textToDisplay = @SQL2, @debug =0
END
ELSE
BEGIN
EXEC (@SQL2)
END
end
SELECT @i = @i 1
if @i >= @Limit
SET @sql2 = null
end
基本上:
XML 的每一行都是一個命令
SELECT @sql2 = @XML.value('(/Krishna/text())[sql:variable("@i") cast as xs:int?][1]', 'varchar(max)')
我的問題是:
如何將GO長腳本中的 every 替換為 XML 中的新行?
每次我遇到一個GO,它GO被洗掉但從那個地方開始是line我的 XML 中的一個新的。
這是一個有效的代碼和 XML 示例:
這是代碼:
---------------------------------------
----check the data
---------------------------------------
GO
SELECT [@@TRANCOUNT]=@@TRANCOUNT
TRUNCATE TABLE #the_inserts
TRUNCATE TABLE #VICASA477
INSERT INTO #the_inserts(RADHE1)
SELECT RADHE1='use apcore;' CHAR(10) CHAR(13) 'exec sp_count ' '''' E.AP_NAME2 ''''
FROM #E E
DECLARE @XML3 XML
SELECT @XML3 = (SELECT #the_inserts.radhe1 AS Krishna FROM #the_inserts FOR XML PATH(''))
INSERT INTO #VICASA477
EXEC sp_execXML @dbname=N'APCore'
,@XML=@xml3
,@DEBUG=0
,@PrintOnly=0
select @XML3
SELECT * FROM #vicasa477
GO
這是 XML:(部分觀點,但你明白了)
<Krishna>use apcore;
exec sp_count '[sub].[matchAgreementEmailSent]'</Krishna>
<Krishna>use apcore;
exec sp_count '[sub].[receivedLog]'</Krishna>
<Krishna>use apcore;
exec sp_count '[sub].[repl_Airline]'</Krishna>
<Krishna>use apcore;
exec sp_count '[sub].[repl_Airport]'</Krishna>
<Krishna>use apcore;
exec sp_count '[sub].[repl_ArrivalCalendar]'</Krishna>
<Krishna>use apcore;
exec sp_count '[sub].[repl_Aupair]'</Krishna>
<Krishna>
結果在這里:(部分觀點,但你明白了)

uj5u.com熱心網友回復:
編輯:正如@DavidBrowne 所提到的,如果需要更改當前資料庫,則此答案不起作用USE。
您可以使用游標運行此腳本,游標分別執行每個批次。
要拆分批次,我們需要使用 XQuery。Krishna由于批次再次被同一個節點分開,而不是每個批次都包含在單獨的子節點中,這使得這變得更加復雜。
DECLARE @sql nvarchar(max), @crsr CURSOR;
SET @crsr = CURSOR FAST_FORWARD READ_ONLY FOR
SELECT
x.krsh.query('
let $go := .
let $prev := /Krishna[. << $go][text() = "GO"][1]
return /Krishna[text() != "GO"][. << $go and not(. << $prev)]/text()
').value('text()[1]','nvarchar(max)') line
FROM @xml.nodes('/Krishna[text() = "GO"]') x(krsh);
OPEN @crsr;
GOTO Ftch;
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC sp_executesql @sql;
ftch:
FETCH NEXT FROM @crsr
INTO @sql;
END;
db<>小提琴
邏輯是這樣運行的:
- 用于
.nodes抓取所有Krishna包含GO. - 對于其中的每一個,我們運行以下 XQuery 運算式:
- 將當前節點分配給
$go - 找到它之前的包含 的節點
GO。 - 查找所有不包含, 和...的
Krishna節點GO - ...位于
$go...之前 - ...以及之后
$prev(如果有的話)。 - 回歸內在
text() .query使用and將所有文本連接在一起.value
注意:這假設最終節點始終是GO.
uj5u.com熱心網友回復:
沒有從 TSQL 運行該腳本的好方法。您需要單獨運行每個批次,這可以通過累積每個批次的行數來完成,并在您看到GO. 剝離GO是一種對 DDL 腳本不起作用的 hack,因為許多 DDL 陳述句必須開始一個批處理,或者是批處理中的唯一陳述句。
行不通的事情是像這樣的腳本
use somedb
go
create table foo(id int)
在 TSQL 中,如果您將其決議并執行為:
exec ('use somedb')
exec ('create table foo(id int)')
資料庫背景關系將在第一批內切換,但在第一次動態 SQL 呼叫結束時恢復為原始資料庫背景關系。您根本無法為動態 SQL 中的會話永久更改資料庫背景關系。因此,您的前處理器必須將資料庫背景關系切換與后續批次連接起來。例如
exec ('use somedb
create table foo(id int)')
如果您的腳本生成完全相同并且您可靠地識別陳述句,這可能會起作用。use database但它很復雜,基本上不值得做。而是使用像 powershell 的“invoke-sqlcmd”這樣的外部程式sqlcmd,或者甚至像 .NET 這樣的客戶端程式,它可以發出可以永久更改資料庫背景關系的頂級批處理。
您可能會發現其他會話級設定也會有同樣的問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/492709.html
標籤:sql服务器 xml sql-server-2016 动态 sql for-xml
