2010-10-04 25 views
6

J'ai une instruction select qui renvoie une table complète d'instructions SELECT (Elle passe en revue chaque colonne de chaque table et crée un select pour trouver si cette colonne contient des données incorrectes) .Tableau avec instructions Select, exécution de SQL dynamique et valeurs de retour

J'ai besoin de prendre cette table complète d'instructions SELECT, les exécuter et voir si l'une d'entre elles retourne des lignes. Si le nombre (*)> 0, alors je veux imprimer quelques données.

Je pensais que je devais utiliser un curseur, mais je ne sais pas comment j'accomplirais cela.

Voici mon code pour obtenir le nombre de mauvaises données.

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 

Ce retourne un tableau avec des lignes comme:

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

que je dois exécuter cette sélection, et si le nombre (*)> 0, puis imprimer la deuxième colonne. Je ne veux rien afficher dans les résultats ou les messages, sauf s'il y a des données à afficher.

+0

version du serveur SQL utilisez-vous ? –

+1

Est-ce que ma dernière édition a fait ce que vous avez besoin? –

+0

2005 ... (11 caractères de plus) – Martin

Répondre

3

essayez ceci:

DECLARE @SQL nvarchar(max) 
SET @SQL='DECLARE @TempTable table (RowID int identity(1,1), CountOf int, DescriptionOf nvarchar(500));' 
SELECT @[email protected]+';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 @[email protected]+';SELECT * FROM @TempTable WHERE CountOF>0' --make sure there is no truncation of the commands 

EXEC (@SQL) 
+0

Je pourrais juste copier et coller toutes les instructions select de la table et obtenir ceci ... – Martin

+0

'Je dois prendre cette table pleine d'instructions SELECT, les exécuter' n'est pas ce que je vous ai donné? –

+2

@KM, vous avez commodément laissé le reste de cette citation. Permettez-moi de le terminer pour vous: '... et voyez si l'un d'entre eux retourne des lignes. Si le nombre (*)> 0, alors je veux imprimer quelques données. »Avez-vous une chance de travailler pour Fox News? –

0

D'abord, je voudrais changer la chaîne SQL que vous construisez un peu être

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

Cela vous obtenir la chaîne lorsque la condition est remplie et NULL lorsqu'elle est pas.

En ce qui concerne la mécanique du curseur lui-même:

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 
+0

Tout d'abord - sp_executesql prend ntext/nchar/nvarchar ... 2) Ceci affiche juste une tonne de tables avec NULLS. Je pourrais juste faire un choix de la table et obtenir les mêmes résultats – Martin

+0

@Martin: 1. Merci pour le crochet sur le nvarchar. Je savais mieux, mais mes doigts et mon cerveau se déconnectent parfois. 2. J'ai modifié ma réponse pour stocker les résultats dans une table temporaire que vous pouvez interroger à la fin, éliminant ainsi les résultats NULL. –

0

sp_executesql peut accepter des paramètres de sortie:

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;