如何执行存储在表(查询)中的查询(更新)?

问题描述 投票:0回答:3

我正在尝试执行此查询的结果。

SELECT 'UPDATE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] ' + 'SET [' + COLUMN_NAME + '] = RTRIM(LTRIM(SUBSTRING ([' + COLUMN_NAME + '], 2 , LEN ([' + COLUMN_NAME + ']) - 2) )) WHERE LEFT([' + COLUMN_NAME + '], 1) = ' + '''"''' + ' AND RIGHT([' + COLUMN_NAME + '], 1) = ' + '''"'''
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE DATA_TYPE IN ('varchar', 'nvarchar') 
ORDER BY TABLE_NAME, COLUMN_NAME 

它返回更多一行。例如:

UPDATE [dbo].[ACCDB] SET [ACODI] = RTRIM(LTRIM(SUBSTRING ([ACODI], 2 , LEN ([ACODI]) - 2) )) WHERE LEFT([ACODI], 1) = '"' AND RIGHT([ACODI], 1) = '"'
UPDATE [dbo].[ANAGP] SET [CDIVA] = RTRIM(LTRIM(SUBSTRING ([CDIVA], 2 , LEN ([CDIVA]) - 2) )) WHERE LEFT([CDIVA], 1) = '"' AND RIGHT([CDIVA], 1) = '"'

现在,我如何以编程方式执行此行?没有我写存储过程中的每一行?

谢谢,我等了回答。

sql-server tsql sql-server-2008-r2 dynamic-sql
3个回答
0
投票

你在这里要做的是动态SQL;动态构建您的查询。有很多方法可以做到这一点。由于您正在构建多个语句,因此您需要能够一次执行一个语句。 McNets的回答建议使用光标,这是一种常用的方式来完成你所追求的目标。另一种方法是用循环分解你的语句,然后一个接一个地执行它们。

下面的代码首先获取一个表名列表,定义我们最终可能会有多少语句。大多数情况下,ID列是我们在这里关心的。然后有一个WHILE循环为每个表运行一次查询,并检查以确保我们需要执行该表的语句。

DECLARE @SqlText NVARCHAR(2000) --Variable to hold your query
       ,@Counter INT            --Counter to keep track of where we are in the loop
       ,@EndLoop INT;           --Value to stop the loop

DECLARE @TblList TABLE (
   [ID] INT IDENTITY(1,1)
  ,[Schema] NVARCHAR(128)
  ,[Table] NVARCHAR(128));

INSERT INTO @TblList ([Schema],[Table])
SELECT 
   TABLE_SCHEMA
  ,TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES;

SELECT @Counter = MIN([ID]), @EndLoop = MAX([ID])
FROM @TblList;

WHILE @Counter <= @EndLoop
  BEGIN

    IF EXISTS ( --If there are no character columns, skip the table
      SELECT 1 
      FROM INFORMATION_SCHEMA.COLUMNS AS col JOIN @TblList AS tbl
      ON tbl.[Schema] = col.TABLE_SCHEMA
      AND tbl.[Table] = col.TABLE_NAME
      AND tbl.[ID] = @Counter
      AND col.DATA_TYPE IN ('varchar', 'nvarchar')
      )
    BEGIN 
      --Construct the query
      SELECT @SqlText = CAST('UPDATE [' + col.TABLE_SCHEMA + '].[' + col.TABLE_NAME + '] ' + 'SET [' + col.COLUMN_NAME + '] = RTRIM(LTRIM(SUBSTRING ([' + col.COLUMN_NAME + '], 2 , LEN ([' + col.COLUMN_NAME + ']) - 2) )) WHERE LEFT([' + col.COLUMN_NAME + '], 1) = ' + '''"''' + ' AND RIGHT([' + col.COLUMN_NAME + '], 1) = ' + '''"''' AS NVARCHAR(2000))
      FROM INFORMATION_SCHEMA.COLUMNS AS col
      JOIN @TblList AS tbl
        ON tbl.[Schema] = col.TABLE_SCHEMA
        AND tbl.[Table] = col.TABLE_NAME
        AND tbl.[ID] = @Counter
        AND col.DATA_TYPE IN ('varchar', 'nvarchar'); 
      --Run the query
      EXEC sp_executesql @SQL;
    END
    --Increment the counter to move through the table list
    SET @Counter = @Counter + 1;

  END

0
投票

我建议使用CURSOR逐行执行它。

看看我在dba.stackexchange.com上的答案中的一个类似问题。

Restore all IDENTITY seeds (out of sync since database restore)


0
投票
DECLARE @c_Statement VARCHAR(MAX)

DECLARE StatementCursor CURSOR FOR
    SELECT 'UPDATE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] ' + 'SET [' + COLUMN_NAME + '] = RTRIM(LTRIM(SUBSTRING ([' + COLUMN_NAME + '], 2 , LEN ([' + COLUMN_NAME + ']) - 2) )) WHERE LEFT([' + COLUMN_NAME + '], 1) = ' + '''"''' + ' AND RIGHT([' + COLUMN_NAME + '], 1) = ' + '''"'''
  FROM INFORMATION_SCHEMA.COLUMNS 
  WHERE DATA_TYPE IN ('varchar', 'nvarchar') 
  ORDER BY TABLE_NAME, COLUMN_NAME

OPEN StatementCursor
FETCH NEXT FROM StatementCursor INTO @c_Statement

WHILE @@FETCH_STATUS = 0
BEGIN

    EXEC(@c_Statement)

    FETCH NEXT FROM StatementCursor INTO @c_Statement

END

CLOSE StatementCursor
DEALLOCATE StatementCursor

您可能需要检查QUOTENAME()函数以将对象名称包装在引号中,而不是在表达式中对它们进行硬编码。您还需要检查错误(TRY / CATCH)并验证您的用户权限以更新结果行。

如果您有多个数据库,INFORMATION_SCHEMA.COLUMNS将仅列出当前连接中的数据库。

© www.soinside.com 2019 - 2024. All rights reserved.