了解动态SQL

时间:2018-07-10 10:08:38

标签: sql-server sql-server-2008 dynamic-sql

在尝试理解动态SQL的过程中,我尝试通过从sys.tables的每个表中动态插入行数的计数来开始简单。

这是我的代码:

SELECT 
    Name, ROW_NUMBER() OVER (ORDER BY NEWID() ) AS SomeNumb
INTO
    #Dyn
FROM 
    sys.tables

CREATE TABLE ##Results (Cnt INT)    

DECLARE @Table NVARCHAR(100)
DECLARE @Counter INT

SET @Counter = 1
SET @Table = (SELECT Name FROM #Dyn WHERE SomeNumb = @Counter)

DECLARE @Sql NVARCHAR(1000)

WHILE @Counter <= (SELECT COUNT(*) FROM #Dyn)
BEGIN
    INSERT INTO ##ResultsTable
    SELECT @Sql = 'SELECT COUNT(*) AS Cnt FROM #Dyn WHERE 
    Name = ' + @Table + 'AND SomeNumb = ' + @Counter
    EXECUTE (@Sql)

    SET @Counter = @Counter + 1
    SET @Sql = ''
END

SELECT * FROM ##ResultsTable

唯一的好处是不会出错。虽然这可能会给我一些指导。我知道我的ResultsTable存在范围问题,但是我认为使用##而不是#可以解决此问题。

任何指针都将受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

一种方法不是使用WHILEsys.tables循环,而是使用sys.schemasFOR XML PATHDECLARE @SQL nvarchar(MAX); SET @SQL = (SELECT N'SELECT ''' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.name) +''' AS ObjectName, COUNT(*) AS [RowCount]' + NCHAR(10) + N'FROM ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + N';' + NCHAR(10) FROM sys.tables t JOIN sys.schemas s ON t.SCHEMA_ID = s.SCHEMA_ID FOR XML PATH(N'')) PRINT @SQL; CREATE TABLE #Cnt (ObjectName sysname, [RowCount] int); INSERT INTO #Cnt (ObjectName, [RowCount]) EXEC sp_executesql @SQL; SELECT * FROM #cnt; DROP TABLE #cnt;

sp_msforeachtable

或者,您可以使用未记录的过程CREATE TABLE #Cnt (ObjectName sysname, [RowCount] int); INSERT INTO #Cnt (ObjectName, [RowCount]) EXEC sp_msforeachtable N'SELECT ''?'' AS ObjectName, COUNT(*) AS [RowCount] FROM ?;'; SELECT * FROM #cnt; DROP TABLE #cnt;

CURSOR

但是,如果我没记错的话,后一种方法实际上确实使用了{ "status":"true", "select":[ { "Type":"MARKET_WORKING", "Question":"WHICH BRAND COUNTER IS IT?", "option1":"USPA", "option2":"HANES", "option3":"USPA & HANES ", "option4":"" } ], "text":[ { "Type":"MARKET_WORKING", "Question":"WHAT IS THE STOCK QTY AVAILABLE OF INNERWEARS?", "option1":"INNERWEARS TOP ", "option2":"INNERWEARS BOTTOM ", "option3":"", "option4":"" }, { "Type":"MARKET_WORKING", "Question":"WHAT IS THE STOCK QTY AVAILABLE OF COMFORTWEAR?", "option1":"COMFORT WEAR TOP", "option2":"COMFORT WEAR BOTTOM", "option3":"", "option4":"" } ] }

答案 1 :(得分:0)

您在这里查看了脚本。

IF OBJECT_ID('tempdb..#Dyn') IS NOT NULL
    DROP TABLE #Dyn

SELECT Name, ROW_NUMBER() OVER (ORDER BY NEWID() ) AS SomeNumb
INTO #Dyn
FROM sys.tables

IF OBJECT_ID('tempdb..#ResultsTable') IS NOT NULL
    DROP TABLE #ResultsTable

CREATE TABLE #ResultsTable (TotalRowCount INT)

DECLARE @Counter INT = 1
DECLARE @Sql NVARCHAR(MAX)

WHILE @Counter <= (SELECT COUNT(*) FROM #Dyn)
BEGIN

    DECLARE @Table NVARCHAR(100) = (SELECT Name FROM #Dyn WHERE SomeNumb = @Counter)

    SELECT @Sql = '
        INSERT INTO #ResultsTable (TotalRowCount)
        SELECT COUNT(*) AS Cnt 
        FROM #Dyn 
        WHERE Name = ''' + @Table + ''' AND SomeNumb = ' + CONVERT(NVARCHAR(10), @Counter)

    EXECUTE (@Sql)

    SET @Counter += 1

END


SELECT * FROM #ResultsTable

有些事情要提:

  • 您可以在EXEC外部创建一个临时表,然后将其插入动态SQL中。
  • 您的COUNT()表中的#Dyn将始终返回1,因为只有1条记录具有特定的表名。
  • 在动态SQL上打印varchar值(例如@Table)时,您需要添加其他引号:
  • 构建动态SQL(例如VARCHAR)时,需要将所有非文字值都转换为NVARCHAR@Counter

编辑:如果您希望每个表的实际计数,则无需查询#Dyn

SELECT @Sql = '
    INSERT INTO #ResultsTable (TotalRowCount)
    SELECT COUNT(*) AS Cnt 
    FROM ' + QUOTENAME(@Table) +

EXECUTE (@Sql)