2011-12-02 61 views
6

我有我想要應用於許多表的代碼,而不是簡單地複製和替換表名,我想使用某種循環或光標來簡化事情。動態SQL中的循環

我設想設置我的表名稱的數組,並使用索引來遍歷列表,檢索每個表名稱並使用動態SQL來散佈表格名稱(如果適用的話在我的代碼中)。

由於沒有'數組'構造,據我所知,在SQL中,我不知道這是如何工作的。

有關如何解決這個問題的任何想法?

回答

7

這裏是做這件事的一種方法:

--Declare a table variable to hold your table names (and column names in case needed) 
declare @listOfTablesToUpdate table (tableName varchar(100), columnNameToUpdate varchar(50)) 

--insert the tables that you want to work with. 
insert into @listOfTablesToUpdate values ('Table1', 'column2') 
insert into @listOfTablesToUpdate values ('Table2', 'column3') 
insert into @listOfTablesToUpdate values ('Table3', 'column4') 

--Cursor for iterating 
declare @tableCursor cursor, 
     @tableName varchar(100), 
     @columnName varchar(50) 

set @tableCursor = cursor for select * from @listOfTablesToUpdate 

open @tableCursor 
fetch next from @tableCursor into @tableName, @columnName 
while(@@fetch_status = 0) 
begin 
    --dynamic sql 
    declare @sql varchar(max) 

    --Your logic here...this is just an example 
    set @sql = 'update '[email protected]+' set '[email protected]+' = '+<value>+' where '[email protected] +' = '+<someothervalue> 
    exec @sql 

    fetch next from @tableCursor into @tableName, @columnName 
end 

close @tableCursor 
deallocate @tableCursor 
+1

+1表變量是工作就像一個魅力陣列 – brian

+0

一個偉大的替代,謝謝! – Chris

0

另一種方法包括:準備一個輔助功能,並允許一個不同的SQL語句應用到每個對象的程序(表,數據庫,等等)在一個列表中。幫助器函數來自SSRS Parameter question,並將逗號分隔列表拆分爲表格。

-- from https://stackoverflow.com/questions/512105/passing-multiple-values-for-a-single-parameter-in-reporting-services 
CREATE FUNCTION [dbo].[fn_MVParam] 
    (@RepParam NVARCHAR(4000), @Delim CHAR(1)= ',') 
RETURNS @Values TABLE (Param NVARCHAR(4000))AS 
    BEGIN 
    DECLARE @chrind INT 
    DECLARE @Piece NVARCHAR(100) 
    SELECT @chrind = 1 
    WHILE @chrind > 0 
    BEGIN 
     SELECT @chrind = CHARINDEX(@Delim,@RepParam) 
     IF @chrind > 0 
     SELECT @Piece = LEFT(@RepParam,@chrind - 1) 
     ELSE 
     SELECT @Piece = @RepParam 
     INSERT @Values(Param) VALUES(CAST(@Piece AS VARCHAR)) 
     SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam) - @chrind) 
     IF LEN(@RepParam) = 0 BREAK 
    END 
    RETURN 
    END 
GO 

下面是ProcessListSQL過程的代碼。

-- @SQL to execute shall include {RP} as the replacement expression that 
-- will evaluate to all the items in the comma delimited list 
-- Also, please include a double quote " rather than two single quotes '' 
-- in the input statement. 

CREATE PROCEDURE [dbo].[ProcessListSQL] (
    @CommaDelimitedList AS NVARCHAR(MAX), 
    @SQLtoExecute AS NVARCHAR(MAX)) 
AS BEGIN 

DECLARE @Statements TABLE 
( PK INT IDENTITY(1,1) PRIMARY KEY, 
    SQLObject NVARCHAR (MAX) 
) 

SET @SQLtoExecute = REPLACE (@SQLtoExecute, '"', '''') 

INSERT INTO @Statements 
SELECT PARAM FROM [dbo].[fn_MVParam](@CommaDelimitedList,',') 

DECLARE @i INT 
SELECT @i = MIN(PK) FROM @Statements 
DECLARE @max INT 
SELECT @max = MAX(PK) FROM @Statements 

DECLARE @SQL AS NVARCHAR(MAX) = NULL 
DECLARE @Object AS NVARCHAR(MAX) = NULL 

WHILE @i <= @max 
    BEGIN  
     SELECT @Object = SQLObject FROM @Statements WHERE PK = @i  
     SET @SQL = REPLACE(@SQLtoExecute, '{RP}', @Object) 

     -- Uncommend below to check the SQL 
     -- PRINT @SQL 

     EXECUTE sp_executesql @SQL 

     SELECT @Object = NULL 
     SELECT @SQL = NULL 
     SET @i = @i + 1 
    END 
END  
GO 

ProcessListSQL過程需要兩個參數。第一個是逗號分隔的字符串,其中包含將要循環的對象列表。第二個參數是一個字符串,其中包含將與第一個參數中的每個對象一起執行的SQL。

在下面的例子中,創建了四個數據庫。請注意,{rp}被第一個參數中的每個對象替換,並且在SQL語句中需要單引號的每個地方都需要雙引號。

EXECUTE ProcessListSQL 'rice,apples,cheese,tomatos', 
'CREATE DATABASE [{rp}] CONTAINMENT = NONE 
     ON PRIMARY (NAME = N"{rp}", 
     FILENAME = N"D:\data\user\{rp}.mdf" , 
     SIZE = 4096KB , 
     FILEGROWTH = 1024KB) 
     LOG ON 
    (NAME = N"{rp}_log", 
     FILENAME = N"D:\DATA\USER\{rp}_log.ldf" , 
     SIZE = 1024KB , 
     FILEGROWTH = 10%)'