2016-05-25 85 views
0

的我有什麼簡單的例子:是否可以從這個動態查詢中移除遊標?

兩個表(TABLE_1和TABLE_2),其中有一個類似的列(同上),但也有幾個「有效載荷」用不同的名稱(col_1_1,col_2_1,col_2_2)列。對於不同的表格,「有效載荷」列的數量是不同的。

我有興趣從兩個表中提取ID到另一個表中所有「有效載荷」列爲空的行。

沒有爲所有表中的所有「有效載荷」欄可以使用(#TEMP)

這是它是如何用遊標完成的列表:

CREATE TABLE #temp (tab nvarchar(20) not null, col nvarchar(20) not null) 
INSERT INTO #temp SELECT 'table_1','col_1_1' UNION SELECT 'table_2','col_2_1' UNION SELECT 'table_2','col_2_2' 

DECLARE @table_name nvarchar(20) 
DECLARE @sql nvarchar(max) 

DECLARE curs CURSOR FOR (SELECT DISTINCT tab FROM #temp) 
OPEN curs 
FETCH NEXT FROM curs INTO @table_name 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    SELECT @sql = ISNULL(@sql,'')+col+' IS NULL AND ' FROM #temp WHERE tab = @table_name 
    SET @sql += 'Id IS NOT NULL' 
    SET @sql = 'INSERT INTO #temp_master SELECT ID FROM '[email protected]_name+' WHERE '[email protected] 
    print @sql 
    SET @sql = '' 
    FETCH NEXT FROM curs INTO @table_name 
END 
CLOSE curs 
DEALLOCATE curs 

這是結果:

INSERT INTO #temp_master SELECT ID FROM table_1 WHERE col_1_1 IS NULL AND Id IS NOT NULL 
INSERT INTO #temp_master SELECT ID FROM table_2 WHERE col_2_1 IS NULL AND col_2_2 IS NULL AND Id IS NOT NULL 

是否可以刪除遊標以獲得相同的結果動態查詢?問題是,當我刪除遊標時,我無法爲不同的表使用動態「IS NULL AND」部分。

+0

如果您想更改對象名稱(tables/databases/schemas/...),您將不得不使用動態SQL。 – mxix

回答

2

有可能擺脫那個遊標。這可能是你所需要的:

CREATE TABLE #temp (tab nvarchar(20) not null, col nvarchar(20) not null) 
INSERT INTO #temp SELECT 'table_1','col_1_1' UNION SELECT 'table_2','col_2_1' UNION SELECT 'table_2','col_2_2' 

DECLARE @table_name nvarchar(20) 
DECLARE @sql nvarchar(max) = '' 

select @sql = 'INSERT INTO #temp_master SELECT ID FROM ' + t.tab + ' WHERE Id IS NOT NULL AND ' + substring(t.cols, 0, len(t.cols)-3) + ' 
' + @sql from 
(
SELECT 
distinct 
    t2.tab, 
    stuff(
    (
    select t1.col + cast(' IS NULL AND ' as varchar(max)) 
    from #temp t1 
    WHERE t1.tab = t2.tab 
    order by t1.tab 
    for xml path('') 
    ), 1, 0, '') AS cols 
FROM 
    #temp t2 
    ) as t 
order by t.tab desc 

print @sql 

drop table #temp 
+0

謝謝,效果很好。 –

1

這是一個普通的CONCAT問題,你可以找到很多方法來完成它沒有光標。其中一種方法是順便說一下游標,對於這樣的任務並不是那麼糟糕。

另一種越來越流行 - FOR XML可以保證,如果任何定義行順序:

DECLARE @sql VARCHAR(MAX) 

CREATE TABLE #temp (tab nvarchar(20) not null, col nvarchar(20) not null) 
INSERT INTO #temp SELECT 'table_1','col_1_1' UNION SELECT 'table_2','col_2_1' UNION SELECT 'table_2','col_2_2' 

SET @sql = (SELECT ( 
SELECT ' 
INSERT INTO #temp_master (ID) SELECT t.ID FROM '+t.tab +' t WHERE t.Id IS NOT NULL' 
    + (select ' AND t.' + tt.col + ' is NULL' from #temp tt WHERE tt.tab = t.tab FOR XML PATH(''), TYPE).value('.', 'varchar(max)') 
FROM #temp t 
GROUP BY t.tab 
FOR XML PATH(''), TYPE).value('.', 'varchar(max)')) 

PRINT @sql 

DROP TABLE #temp 

有點「棘手」的事情是,你有兩件事情塌陷:

  • 許多查詢(具體表分開)
  • 每列多列

所以你有一個內部的FOR XML摺疊每個表和另一個列 - 將所有查詢合併成一個大腳本。

+0

這也可以,謝謝 –

相關問題