2013-01-31 8 views

risposta

9

Non esiste alcuna procedura speciale all'interno di SQL Server per effettuare questa determinazione. È necessario interrogare ogni tabella. Ecco una soluzione di forza bruta:

If object_id('tempdb..#Results') is not null 
    Drop Table #Results; 
GO 
Create Table #Results 
    (
    TableSchema sysname not null 
    , TableName sysname not null 
    , ColumnName sysname not null 
    ); 
GO 

Declare @TableSchema sysname; 
Declare @TableName sysname; 
Declare @ColumnName sysname; 
Declare @DataType sysname; 
Declare @Columns Cursor; 
Declare @BaseSql nvarchar(max); 
Declare @Sql nvarchar(max); 
Declare @AdditionalFilter nvarchar(max); 

Set @BaseSql = 'Insert #Results(TableSchema, TableName, ColumnName) 
       Select ''TABLE_SCHEMA'', ''TABLE_NAME'', ''COLUMN_NAME'' 
       From (Select 1 As V) As Z 
       Where Not Exists (
            Select 1 
            From [TABLE_SCHEMA].[TABLE_NAME] 
            Where [COLUMN_NAME] Is Not Null 
             ADDITIONAL_FILTER 
            )'; 

Set @Columns = Cursor Fast_Forward For 
    Select C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME, C.DATA_TYPE 
    From INFORMATION_SCHEMA.COLUMNS As C 
     Left Join INFORMATION_SCHEMA.VIEWS As V 
      On V.TABLE_SCHEMA = C.TABLE_SCHEMA 
       And V.TABLE_NAME = C.TABLE_NAME 
    Where V.TABLE_NAME Is Null; 

Open @Columns; 
Fetch Next From @Columns Into @TableSchema, @TableName, @ColumnName, @DataType; 

While @@Fetch_Status = 0 
Begin 
    If @DataType In('int','smallint','tinyint','bigint','numeric','bit','decimal','money','smallmoney','float','real') 
     Set @AdditionalFilter = 'And [COLUMN_NAME] <> 0'; 
    Else If @DataType In('char','nchar','varchar','nvarchar','text','ntext') 
     Set @AdditionalFilter = 'And Len([COLUMN_NAME]) > 0'; 
    Else 
     Set @AdditionalFilter = ''; 

    Set @Sql = Replace(@BaseSql, 'ADDITIONAL_FILTER', @AdditionalFilter); 
    Set @Sql = Replace(@Sql, 'TABLE_SCHEMA', @TableSchema); 
    Set @Sql = Replace(@Sql, 'TABLE_NAME', @TableName); 
    Set @Sql = Replace(@Sql, 'COLUMN_NAME', @ColumnName); 

    --Print @Sql 
    Exec(@Sql) 
    Fetch Next From @Columns Into @TableSchema, @TableName, @ColumnName, @DataType; 
End 

Close @Columns; 
Deallocate @Columns; 

Select * 
From #Results 

Uno intralcio nella soluzione sopra è che ogni colonna da una tabella che è vuota verrà restituito. Se si desidera escludere tabelle vuote, è necessario modificare la query solo come segue:

Set @BaseSql = 'Insert #Results(TableSchema, TableName, ColumnName) 
       Select ''TABLE_SCHEMA'', ''TABLE_NAME'', ''COLUMN_NAME'' 
       From (Select 1 As V) As Z 
       Where Exists (
           Select 1 
           From [TABLE_SCHEMA].[TABLE_NAME] 
           ) 
       And Not Exists (
           Select 1 
           From [TABLE_SCHEMA].[TABLE_NAME] 
           Where [COLUMN_NAME] Is Not Null 
            ADDITIONAL_FILTER 
           )'; 
+0

Molto utile per il tunning del database (ho molte colonne inutilizzate che dovrei lasciare: S). Ho appena aggiunto il tipo di dati e un ordine dall'ultimo SELECT. Grazie! – Roimer

+0

"Il testo del tipo di dati dell'argomento non è valido per l'argomento 1 della funzione len" si verifica quando si esegue il codice precedente. Sarebbe meglio usare ** DATALENGTH **? –

+0

@adolfgarlic - Si potrebbe anche usare la funzione 'DataLength'. Ho il sospetto che la funzione Len potrebbe essere barfing sui tipi di dati 'text' e' ntext'. – Thomas

Problemi correlati