Number of Non NULL Fields in a database

  • I have looked through the metabase views but have not gotten a satisfactory result as of yet.

    Please provide any help, it would be very appreciated.

    Thanks,

    Wes

  • How about this:

    [font="Courier New"]SELECT

       *

    FROM  

       INFORMATION_SCHEMA.Columns

    WHERE

       is_nullable = 'YES'[/font]

  • Thanks for the reply Jack,

    I am looking for the actual number of fields that are not Null in every table in a database.

    For example, I will need to find the number of Columns times the number of Rows in a table, that will give me the total number of all fields in a table. Then I need to subtract the number of Null fields.

    I would need to do this for each table.

    Thanks,

    Wes

  • So you want to know how many non-null values are stored in each column in each table and how many total rows in the table?

    For example I have tableA(id int PK, col1 varchar(10) Not Null, col2 Varchar(10) Null) with 10 rows. You want a return something like this:

    TableName RowCount ColumnName Nulls Non-Nulls

    ---------- --------- ------------ ---- ---------

    tableA 10 id 0 10

    tableA 10 Col1 0 10

    tableA 10 Col2 3 7

  • Yes, exactly!

  • How many tables/columns are we talking about? Do you have some off-peak time to do this in?

    This may not be the "best" or "right" way to get his information, but this code will generate the code you need to get the information. I really don't like this solution, but I can't think of another way to do it. Hopefuly someone else can:

    [font="Courier New"]DECLARE @table TABLE(table_name VARCHAR(255), column_name VARCHAR(255), null_count INT, non_null_count INT, total_count INT)

    DECLARE @sql VARCHAR(MAX), @final_sql VARCHAR(MAX)

    DECLARE c_cols CURSOR FOR

       SELECT

           'Select ''' + table_name + ''' as table_name, ''' + column_name + ''' as column_name, (Select Count([' + column_name + ']) as rows From ' + table_schema + '.' + table_name + ' Where [' + column_name + '] Is Null) as nulls,

    (Select Count([' + column_name + ']) as rows From ' + table_schema + '.' + table_name + ' Where [' + column_name + '] Is Not Null) as non_nulls,

    (Select Count([' + column_name + ']) as rows From ' + table_schema + '.' + table_name + ') as total' AS sql

       FROM  

          INFORMATION_SCHEMA.Columns

       WHERE

           Table_Name LIKE 'a%'

    OPEN c_cols

    FETCH Next FROM c_cols INTO @sql

    WHILE @@FETCH_STATUS = 0

       BEGIN

           SET @final_sql = ISNULL(@final_sql, '') + @sql + ' Union All '

           FETCH Next FROM c_cols INTO @sql

       END

    CLOSE c_cols

    DEALLOCATE c_cols

    PRINT @final_sql[/font]

  • One of the DB's I'm looking at has 188 tables with 2516 columns. Yes I can run during off peak times, but it is actually a replicated Oracle DB, so this DB is for reporting purposes only.

    When I try to run this, I get the following errors,

    Msg 170, Level 15, State 1, Line 3

    Line 3: Incorrect syntax near 'max'.

    Msg 170, Level 15, State 1, Line 4

    Line 4: Incorrect syntax near 'max'.

    Msg 137, Level 15, State 1, Line 16

    Must declare the variable '@sql'.

    Msg 137, Level 15, State 2, Line 20

    Must declare the variable '@final_sql'.

    Msg 137, Level 15, State 1, Line 22

    Must declare the variable '@sql'.

    Msg 137, Level 15, State 2, Line 28

    Must declare the variable '@final_sql'.

    I looked at BOL and the syntax looks correct.

    Thanks again for any help you can supply.

    Wes

  • Are you using SQL 2005? Based on what the errors are I'm guessing you are running SQL 2000 since varchar(max) was added in 2005. Change the max to 8000. This probably means you will need to batch the process. So I'd dump the column sql data into a table with an identity column and run the cursor off that and either have a processed flag or delete the rows as I process them. Something like

    [font="Courier New"]IF OBJECT_ID('dbo.column_sql') IS NULL

       BEGIN

           CREATE TABLE dbo.column_sql

               (

               id INT IDENTITY(1,1) PRIMARY KEY,

               sql_statement VARCHAR(8000)

               )

       END

    ELSE

       BEGIN

           TRUNCATE TABLE dbo.column_sql

       END

    DECLARE @sql VARCHAR(8000), @final_sql VARCHAR(8000), @id INT

    INSERT INTO dbo.column_sql

       (

       sql_statement

       )

       SELECT

            'Select ''' + table_name + ''' as table_name, ''' + column_name + ''' as column_name, (Select Count([' + column_name + ']) as rows From ' + table_schema + '.' + table_name + ' Where [' + column_name + '] Is Null) as nulls,

                    (Select Count([' + column_name + ']) as rows From ' + table_schema + '.' + table_name + ' Where [' + column_name + '] Is Not Null) as non_nulls,

                    (Select Count([' + column_name + ']) as rows From ' + table_schema + '.' + table_name + ') as total' AS sql

       FROM  

          INFORMATION_SCHEMA.Columns

    WHILE EXISTS (SELECT * FROM dbo.column_sql)

       BEGIN

           DECLARE c_sql CURSOR FOR

               SELECT TOP 100

                   id,

                   sql_statement

               FROM

                   dbo.column_sql

               ORDER BY

                   id

           OPEN c_sql

          

           FETCH Next FROM c_sql INTO

               @id,

               @sql

              

           WHILE @@FETCH_STATUS = 0

               BEGIN

                   PRINT ' IN Fetch Loop'

                   SET @final_sql = ISNULL(@final_sql, '') + @sql + ' Union All '

                   DELETE

                   FROM

                       dbo.column_sql

                   WHERE

                       id = @id

              

                   PRINT 'Row deleted'

                   FETCH Next FROM c_sql INTO

                       @id,

                       @sql

               END

              

               SELECT @final_sql

               CLOSE c_sql

               DEALLOCATE c_sql

       END[/font]

  • SQL Server 2005, once I changed the max to 8000 it runs without error. But of course, it only gets halfway throught the first 2 tables.

    The query is running against a SQL Server 2000 instance though, I didn't think about it before. I new max was new to 2005.

    I'm not sure what this is doing. It looks like every "select @final_sql" is selecting the same table and column code.

    Is this what it is suppose to do? Or do I need to add some code to make it work?

    Thanks again,

    Wes

  • I forgot to reset the @final_sql variable so it was continually adding on. Down where you close the cursor put in Set @final_sql = ''. You may also want to check the length of the variable and when it gets to 8000 kick out as well. Something like Len(@final_sql + @sql) < 8000 added to the @@FETCH_STATUS.

  • Thanks Jack,

    I think I can make this work. The NULL column is always 0 because of the concatenation (I guess) but I am only concerned about the non-null fields.

    When I try to run the resulting query, I get the following error:

    Msg 279, Level 16, State 2, Line 1

    The text, ntext, and image data types are invalid in this subquery or aggregate expression.

    Any ideas?

    Thanks again,

    Wes

  • I see why I am getting the error, but do you know how I can cast those datatypes dynamically in the cursor?

    Thanks,

    Wes

  • I found there was only one column in this DB, so I excluded it in the cursor until I figure something else out.

    But now I get this error:

    Msg 8621, Level 17, State 1, Line 1

    Internal Query Processor Error: The query processor ran out of stack space during query optimization.

    Any help would be very appreciated!

    Thanks,

    Wes

  • According to this:

    If you have more than 255 UNION ALL statements, you will get the above error. There is a hotfix available and we are still on sp3a. I guess it's time to install SP4.

    Thanks for all your help Jack,

    Wes

Viewing 14 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic. Login to reply