Как найти, какие столбцы не имеют данных (все значения NULL)?
У меня есть несколько таблиц в базе данных. Я хотел бы найти, какие столбцы (в которых таблицы) не имеют никаких значений (все NULL в столбце). В приведенном ниже примере результат должен быть
TestTable1 --> Var2
TestTable2 --> Variable1
Я не знаю, как создать такой запрос. Ваша помощь очень ценится!
--create first table
create table dbo.TestTable1 (
sur_id int identity(1,1) not null primary key,
var1 int null,
var2 int null
)
go
--insert some values
insert into dbo.TestTable1 (var1)
select 1 union all select 2 union all select 3
--create second table
create table dbo.TestTable2 (
sur_id int identity(1,1) not null primary key,
variable1 int null,
variable2 int null
)
--and insert some values
insert into dbo.TestTable2 (variable2)
select 1 union all select 2 union all select 3
Ответы
Ответ 1
Для одного столбца count(ColumnName)
возвращает число строк, где ColumName
не равно null:
select count(TheColumn)
from YourTable
Вы можете создать запрос для всех столбцов. По предложению Мартина вы можете исключить столбцы, которые не могут иметь значение null с is_nullable = 1
. Например:
select 'count(' + name + ') as ' + name + ', '
from sys.columns
where object_id = object_id('YourTable')
and is_nullable = 1
Если количество таблиц велико, вы можете сгенерировать запрос для всех таблиц аналогичным образом. Список всех таблиц находится в sys.tables
.
Ответ 2
Обновлено.... Хорошо, мне было очень весело с этим
. Proc принимает два параметра: таблицу для поиска и критерии для применения. вы можете передать по существу и где предложение ко второму параметру. Я написал proc, чтобы интерпретировать двойные кавычки назад к одинарным кавычкам.... снова это было построено на основе оригинальных концепций разработчиков.
GO
/****** Object: StoredProcedure [dbo].[SearchAllTables] Script Date: 05/04/2011 14:29:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROC [dbo].[SearchAllTables2] ( @SEARCH_TABLE NVARCHAR(255), @CONDITION AS NVARCHAR(MAX) ) AS
BEGIN
-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
-- Written by: Narayana Vyas Kondreddi -- Site: http://vyaskn.tripod.com
-- Tested on: SQL Server 7.0 and SQL Server 2000
-- Date modified: 28th July 2002 22:50 GMT
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110), @COND_STR NVARCHAR(MAX)
SET @TableName = ''
--SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @CONDITION = REPLACE(@CONDITION,'"','''')
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE = 'BASE TABLE'
AND
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0 AND TABLE_NAME = @SEARCH_TABLE
) WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN SET @ColumnName = (
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) AND
TABLE_NAME = PARSENAME(@TableName, 1) AND QUOTENAME(COLUMN_NAME) > @ColumnName )
IF @ColumnName IS NOT NULL
BEGIN
SET @COND_STR = REPLACE(@CONDITION,'''','"')
INSERT INTO #Results
EXEC ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''',''' + @COND_STR + ''' AS CONDITION FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' ' + @CONDITION)
PRINT ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''',''' + @COND_STR + ''' AS CONDITION FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' ' + @CONDITION)
END
END
END
SELECT ColumnName, ColumnValue
FROM #Results
END
GO
-- to execute
exec [SearchAllTables2] 'TABLENAME','LIKE "%DOUG%"' -- double quotes are automatically escaped to single quotes...
Оригинальный код, измененный в соответствии с авторским правом ниже... только с использованием частей.
GO
/****** Object: StoredProcedure [dbo].[SearchAllTables] Script Date: 05/04/2011 14:29:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROC [dbo].[SearchAllTables2] ( @TABLE_NAME NVARCHAR(255) ) AS
BEGIN
-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
-- Written by: Narayana Vyas Kondreddi -- Site: http://vyaskn.tripod.com
-- Tested on: SQL Server 7.0 and SQL Server 2000
-- Date modified: 28th July 2002 22:50 GMT
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET @TableName = ''
--SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE = 'BASE TABLE'
AND
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0 AND TABLE_NAME = @TABLE_NAME
) WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN SET @ColumnName = (
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) AND
TABLE_NAME = PARSENAME(@TableName, 1) AND QUOTENAME(COLUMN_NAME) > @ColumnName )
IF @ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''', ''IS NULL'' FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' IS NULL ')--LIKE ' + @SearchStr2 )
--PRINT ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''', ''IS NOT NULL'' FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' IS NOT NULL ')--LIKE ' + @SearchStr2 )
END
END
END
SELECT ColumnName, ColumnValue
FROM #Results
END
GO
-- to execute
exec [SearchAllTables2] 'Master'
Ответ 3
Здесь script Я написал для того же, это двухэтапный ручной процесс:
- Запустите этот script в SSMS и выберите все строки на панели результатов:
SELECT
'SELECT
COUNT( DISTINCT [' + COLUMN_NAME + ']) AS UniqueValues,
''' + TABLE_NAME + '.' + COLUMN_NAME + ''' AS ColumnName
FROM
[' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']
UNION ALL
'
FROM
INFORMATION_SCHEMA.COLUMNS
ORDER BY
TABLE_NAME,
COLUMN_NAME
- Вставьте результаты в новое окно запроса. Прокрутите до самого низа и удалите завершающий оператор
UNION ALL
. Он будет выглядеть следующим образом:
SELECT COUNT( DISTINCT [ModifiedByUserId]) AS UniqueValues, 'Inspections.ModifiedByUserId' AS ColumnName FROM [dbo].[Inspections] UNION ALL
SELECT COUNT( DISTINCT [Notes]) AS UniqueValues, 'Inspections.Notes' AS ColumnName FROM [dbo].[Inspections] UNION ALL
SELECT COUNT( DISTINCT [PublicPassword]) AS UniqueValues, 'Inspections.PublicPassword' AS ColumnName FROM [dbo].[Inspections] UNION ALL
SELECT COUNT( DISTINCT [ShopId]) AS UniqueValues, 'Inspections.ShopId' AS ColumnName FROM [dbo].[Inspections] UNION ALL
SELECT COUNT( DISTINCT [Status]) AS UniqueValues, 'Inspections.Status' AS ColumnName FROM [dbo].[Inspections] UNION ALL
SELECT COUNT( DISTINCT [SupervisorUserId]) AS UniqueValues, 'Inspections.SupervisorUserId' AS ColumnName FROM [dbo].[Inspections] UNION ALL
- Запустите запрос. Для работы в базе данных из 300 столбцов потребовалось около 6 минут. Это будет быстрее или медленнее в зависимости от того, сколько индексов используется.
Ответ 4
Это слишком полезно, чтобы не вставляться в удобный небольшой процесс системы, особенно если вы только что унаследовали устаревшую базу данных и задаетесь вопросом, какие столбцы вы можете отбросить или проигнорировать.
/*
Show the count of not-null values in a table
*/
create proc sp_aaShowAllNullColumns @tableName varchar(255) as
begin
set nocount on
declare @sql nvarchar(4000)
declare @cols nvarchar(4000)
declare @tcols table( colbit nvarchar(255) )
insert @tcols
select 'count(' + name + ') as ' + name + ', ' as colbit
from sys.columns
where object_id = object_id(@tableName)
and is_nullable = 1
select @cols = coalesce( @cols, ', ', '' ) + colbit from @tcols
select @cols = substring( @cols, 1, (len(@cols) - 1) )
select @cols = isnull( @cols, '' )
select @sql = 'select count(*) as Rows' + @cols + ' from ' + @tableName
exec sp_executeSql @sql
end
go
exec sys.sp_MS_marksystemobject 'sp_aaShowAllNullColumns'
go
use Bookshop
go
exec sp_aaShowAllNullColumns 'Books'
go
Ответ 5
Здесь bash-скрипт, который для всех непустых таблиц в базе данных SQLite (или для всех указанных таблиц в такой базе данных) идентифицирует столбцы со значением NULL. Та же самая техника может использоваться на языке программирования по вашему выбору, при условии, что он может общаться с базой данных SQLite.
#!/bin/bash
function help {
cat <<EOF
Syntax: $0 databasefile [table ...]
If no tables are specified, then for each non-empty user table in the
specified SQLite database row, this script will emit the column names
of those columns in which all the values are NULL. If any tables are
specified, only the specified tables are scanned.
The script is written to make it easy to modify the criteria and the output.
Thanks to SQL, two passes are required per table, and if no tables are
specified, an additional invocation of sqlite3 is required.
Column names are written in the form: tablename.columnname
Requirements:
sqlite3 on the \$PATH
Options:
-v | --verbose :: emit additional information
EOF
}
while [ "$1" ]
do case "$1" in
-h | --help | "" ) help
exit
;;
-v | --verbose ) VERBOSE=1
shift
;;
* ) break
;;
esac
done
function verbose { if [ "$VERBOSE" ] ; then echo "[email protected]" >&2 ; fi ; }
db="$1"
shift
if [ ! -s "$db" ] ; then echo "$0 : $db not found" ; exit ; fi
# To prevent loading ~/.sqliterc specify -init ""
# Global: db
function nullcolumns {
local table="$1"
local count column field nulls
( read count
if [ -n "$count" ] ; then
verbose "Row count for $table: $count"
if [ "$count" -gt 0 ] ; then
while read column ; do
echo "SELECT '$column', * FROM
(SELECT COUNT(*) FROM $table WHERE '$column' IS NULL);"
done |
sqlite3 -readonly "$db" | while IFS="|" read field nulls ; do
verbose $table.$field ... $nulls
if [ "$nulls" -eq $count ] ; then echo "$table.$field" ; fi
done
else cat > /dev/null
fi
else cat > /dev/null
fi ) < <(sqlite3 -readonly "$db" "select count(*) from '$table';
select name from pragma_table_info( '$table' )")
}
if [ $# = 0 ] ; then
sqlite3 -readonly "$db" .tables | while read table ; do
nullcolumns "$table"
done
else
for table ; do
nullcolumns "$table"
done
fi