2011-12-02 27 views
6

Tengo un código que me gustaría aplicar a varias tablas, pero en lugar de simplemente copiar y reemplazar nombres de tablas, me gustaría usar algún tipo de bucle o cursor para simplificar las cosas.Loops dentro de SQL dinámico

I imaginar la configuración de una matriz de mis nombres de tablas y el uso de un índice para iterar sobre la lista, recuperar cada nombre de tabla y utilizar SQL dinámico para intercalar el nombre de la tabla en mi código.

Dado que no existe una construcción de "matriz", hasta donde yo sé, dentro de SQL, no estoy seguro de cómo funcionaría.

¿Alguna idea sobre cómo hacerlo?

Respuesta

7

Esta es una manera de hacerlo:

--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 Las variables de tabla son una gran sustitución de las matrices – brian

+0

funcionó de maravilla, gracias! – Chris

0

Otro enfoque implica la preparación de una función de ayuda y un procedimiento que permiten aplicar diferentes sentencias SQL para cada objeto (tabla, base de datos, etcétera) en una lista La función auxiliar viene de un SSRS Parameter question y divide una lista delimitada por comas en una tabla.

-- 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 

A continuación se muestra el código para el procedimiento 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 

El procedimiento ProcessListSQL toma dos parámetros. La primera es una cadena delimitada por comas que contiene la lista de objetos por los que se realizará un ciclo. El segundo parámetro es una cadena que contiene el SQL que se ejecutará con cada uno de los objetos en el primer parámetro.

En el siguiente ejemplo, se crean cuatro bases de datos. Tenga en cuenta que {rp} se reemplaza con cada uno de los objetos en el primer parámetro y se necesitan comillas dobles en cada lugar donde se necesitan comillas simples en la instrucción 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%)'