Таблица с утверждениями Select, выполнением динамического SQL и возвращением значений - PullRequest
6 голосов
/ 04 октября 2010

У меня есть оператор выбора, который возвращает таблицу, полную операторов 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

Мне нужно выполнить этот выбор, и если число (*)> 0, то вывести второй столбец. Я не хочу ничего отображать в результатах или сообщениях, если нет данных для показать.

Ответы [ 3 ]

3 голосов
/ 04 октября 2010

попробуйте это:

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)
0 голосов
/ 04 октября 2010

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;   
0 голосов
/ 04 октября 2010

Во-первых, я бы немного изменил строку 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
...