我有代码,我想应用于许多表,而不是简单地复制和替换表名,我想使用某种循环或光标来简化事情。
我设想设置一个表名的数组,并使用索引迭代列表,检索每个表名,并使用动态SQL在我的代码中散布表名。
由于没有“数组”构造,据我所知,在SQL中,我不确定这是如何工作的。
关于如何解决此问题的任何想法?
答案 0 :(得分:11)
这是一种方法:
--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 '+@tableName+' set '+@columnName+' = '+<value>+' where '+@columnName +' = '+<someothervalue>
exec @sql
fetch next from @tableCursor into @tableName, @columnName
end
close @tableCursor
deallocate @tableCursor
答案 1 :(得分: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%)'