【问题标题】:Table with Select Statements, Executing Dynamic SQL and Returning Values带有 Select 语句、执行动态 SQL 和返回值的表
【发布时间】:2011-04-20 22:25:31
【问题描述】:

我有一个 select 语句,它返回一个充满 SELECT 语句的表(它遍历每个表中的每一列,并创建一个选择来查找该列是否包含任何错误数据)。

我需要获取这个充满 SELECT 语句的表,执行它们,并查看它们中是否有任何返回行。如果count(*) > 0,那么我想打印一些数据。

我在想我必须使用光标,但我不知道我将如何做到这一点。

这是我获取不良数据计数的代码。

SELECT 'SELECT count(*),  '' '+sysobjects.name + ' - ' + syscolumns.name + 
    ' '' FROM ['
         +sysobjects.name + '] WHERE UNICODE(SUBSTRING(['+syscolumns.name+'],Len(['+syscolumns.name+']),1)) = 0' 
         FROM sysobjects 
    JOIN syscolumns ON sysobjects.id = syscolumns.id
    JOIN systypes ON syscolumns.xtype=systypes.xtype
   WHERE sysobjects.xtype='U' and systypes.name IN ('varchar', 'nvarchar')
ORDER BY sysobjects.name,syscolumns.colid

这将返回一个包含如下行的表:

SELECT count(*),  ' All_MW_Users - LastName ' FROM [All_MW_Users] WHERE UNICODE(SUBSTRING([LastName],Len([LastName]),1)) = 0

我需要执行这个选择,如果 count(*) > 0,则打印第二列。我不想在结果或消息中显示任何内容,除非有数据显示。

【问题讨论】:

  • 您使用哪个版本的 SQL Server?
  • 我的最新编辑是否符合您的要求?
  • 2005 ...(还有 11 个字符)

标签: sql sql-server sql-server-2005 dynamic-sql


【解决方案1】:

试试这个:

DECLARE @SQL nvarchar(max)
SET @SQL='DECLARE @TempTable table (RowID int identity(1,1), CountOf int, DescriptionOf nvarchar(500));'
SELECT @SQL=@SQL+';INSERT @TempTable (CountOf,DescriptionOf ) SELECT count(*),  '' '+sysobjects.name + ' - ' + syscolumns.name + 
    ' '' FROM ['
         +sysobjects.name + '] WHERE UNICODE(SUBSTRING(['+syscolumns.name+'],Len(['+syscolumns.name+']),1)) = 0' 
         FROM sysobjects 
    JOIN syscolumns ON sysobjects.id = syscolumns.id
    JOIN systypes ON syscolumns.xtype=systypes.xtype
   WHERE sysobjects.xtype='U' and systypes.name IN ('varchar', 'nvarchar')
ORDER BY sysobjects.name,syscolumns.colid

SET @SQL=@SQL+';SELECT * FROM @TempTable WHERE CountOF>0' --make sure there is no truncation of the commands

EXEC (@SQL)

【讨论】:

  • 我可以复制并粘贴表格中的所有选择语句并得到这个...
  • I need to take this table full of SELECT statements, execute them这不是我给你的吗?
  • @KM,您方便地省略了该报价的其余部分。请允许我为你完成它:...and see if any of them return rows. If the count(*) > 0, then I want to print out some data.你有机会为福克斯新闻工作吗?
  • @Abe Miessler,谢谢,但问题并不完全清楚,尤其是在 OP 编辑​​之前。 查看我的最新编辑,我基本上创建了一个表来捕获所有 COUNT(*) 值,然后从该表中选择 count > 0
  • @KM - 在我的编辑中,我所做的只是我想要的粗体......你仍然错过了这条线(就像 Abe 说的那样),所以我只是把它加粗了。但是编辑效果很好......谢谢
【解决方案2】:

首先,我将您正在构建的 SQL 字符串稍微更改为

SELECT CASE WHEN count(*)>0 THEN ' All_MW_Users - LastName ' END FROM [All_MW_Users] WHERE UNICODE(SUBSTRING([LastName],Len([LastName]),1)) = 0 

这将在满足条件时为您提供字符串,而在不满足条件时为您提供 NULL。

至于光标本身的机制:

declare @SQLSTring nvarchar(4000)

create table #tmpResults (
    OutputString nvarchar(1000)
)

declare DynamicSQL cursor for
    {The Select Statement in your question with modification}

open DynamicSQL

while (1=1) begin
     fetch next from DynamicSQL
        into @SQLString

    if @@fetch_status <> 0
        break;

   insert into #tmpResults
       (OutputString)
       exec sp_executesql @SQLString
end /* while */

close DynamicSQL
deallocate DynamicSQL

select OutputString
    from #tmpResults
    where OutputString is not null

【讨论】:

  • 首先 - sp_executesql 需要 ntext/nchar/nvarchar ... 2) 这只会打印出大量带有 NULLS 的表。我可以选择表格并获得相同的结果
  • @Martin:1. 感谢您对 nvarchar 的关注。我知道得更好,但我的手指和大脑有时会断开连接。 2. 我修改了我的答案,将结果存储在一个临时表中,您可以在最后查询,从而消除了 NULL 结果。
【解决方案3】:

sp_executesql 可以接受输出参数:

declare c cursor static forward_only read_only for
SELECT N'SELECT @count = count(*)' +
    N' FROM ' + quotename(s.name) + '.' + quotename(t.name) +
    N' WHERE UNICODE(SUBSTRING(' + quotename(c.name) + N', len('+ quotename(c.name) + N'),1)) = 0x00'
    , s.name as schema_name
    , t.name as table_name
    , c.name as column_name
    from sys.tables t
    join sys.schemas s on t.schema_id = s.schema_id
    join sys.columns c on t.object_id = c.object_id
    join sys.types x on c.user_type_id = x.user_type_id
    where x.name in (N'varchar', N'nvarchar');

open c;

declare @sql nvarchar(max), @s sysname, @t sysname, @c sysname;
fetch next from c into @sql, @s, @t, @c;
while 0 = @@fetch_status
begin
    declare @count bigint = 0;
    print @sql;
    exec sp_executesql @sql, N'@count bigint output', @count output;
    raiserror (N'%s.%s.%s: %I64d', 0,1, @s, @t, @c, @count);
                -- if @count is not 0, act here
    fetch next from c into @sql, @s, @t, @c;
end

close c;
deallocate c;   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    相关资源
    最近更新 更多