在 SQL Server 2008 中,即使没有记录包含这些列的 NULL,我如何才能获得在其架构中标记为可为空的所有列?

IBC*_*IBC 7 sql-server-2008 null

在我的旧数据库中,很多时候模式不必要地允许特定列的空条目。为了帮助找出特别是哪些列,我需要对 SQL Server 2008 进行一些超出我专业水平的查询。我的目标是稍微收紧模式并使自己免于处理代码中的空情况。

一种帮助我解决问题的粗略方法(选项 1)是只获取包含至少一个空条目的所有记录(并选择 *),然后对不包含空条目的列进行目视扫描。我当然可以只使用Where columnA IS NULL OR columnB IS NULL OR columnC IS NULL,但这对于有很多列的表来说变得乏味。此数据库中的某些表包含二十多列!此外,总共有大约500张桌子。因此,通用解决方案是最好的。

以下是三个让我满意的答案选项:

  • 选项 1 :“获取至少其中一列为空的所有记录”。我将查看没有空条目的列。
  • 选项 2:一个更好的答案是一些脚本,它获取包含至少一个空条目的列名列表。然后我将手动查看哪些可空列不在此列表中。
  • 选项 3:最佳答案会为我提供一个列名称列表,这些列名称在其架构中标记为可为空,即使这些列中不存在具有空条目的记录。

谢谢!

小智 8

Martin Smith 的回答非常适合为您提供 SQL 2008 中整个数据库所需的所有列。非常好!

这是我在 SQL 有 CTE 和 PIVOT 之前的日子里的做法。这将与 Martin 的解决方案不起作用的旧版本 SQL 兼容,并且在 2008 年仍然有效,但性能比他的解决方案差。

USE MyDB

SET NOCOUNT ON

CREATE TABLE ##nullable  (
    ID INT IDENTITY(1,1),
    SchName VARCHAR(128),
    TblName VARCHAR(128),
    ColName VARCHAR(128),
    hasNulls BIT,
    PRIMARY KEY(ID)
    )

DECLARE @currTbl VARCHAR(128)
DECLARE @currCol VARCHAR(128)
DECLARE @currSch VARCHAR(128)
DECLARE @limit INT
DECLARE @i INT
DECLARE @sql NVARCHAR(4000)

INSERT INTO ##nullable (
    SchName,
    TblName,
    ColName,
    hasNulls
    )
SELECT
    c.TABLE_SCHEMA,
    c.TABLE_NAME,
    c.COLUMN_NAME,
    0 AS hasNulls
FROM INFORMATION_SCHEMA.COLUMNS c
INNER JOIN INFORMATION_SCHEMA.TABLES t
ON c.TABLE_CATALOG = t.TABLE_CATALOG
AND c.TABLE_NAME = t.TABLE_NAME
AND c.TABLE_SCHEMA = t.TABLE_SCHEMA
WHERE c.IS_NULLABLE = 'YES'
AND t.TABLE_TYPE = 'BASE TABLE'

SET @limit = (SELECT MAX(ID) FROM ##nullable)
SET @i = 1

WHILE @i <= @limit
BEGIN   
    SELECT @currSch = SchName,
        @currTbl = TblName,
        @currCol = ColName
    FROM ##nullable 
    WHERE ID = @i

    SET @sql = 'UPDATE ##nullable 
        SET hasNulls = 1
        WHERE ID = ' + CAST(@i AS VARCHAR(20)) + ' 
        AND EXISTS (SELECT 1 FROM ' + QUOTENAME(@currSch) + '.'+ QUOTENAME(@currTbl) + ' 
        WHERE ' + QUOTENAME(@currCol) + ' IS NULL)'

    EXEC(@sql)

    SET @i = @i + 1     
END

SELECT DISTINCT * FROM ##nullable 
WHERE hasNulls = 0  

DROP TABLE ##nullable
Run Code Online (Sandbox Code Playgroud)


Mar*_*ith 7

您可以使用sys.sp_MSforeachtable循环遍历所有表格并进行如下处理(如果您有包含该'角色的非标准对象名称,则可能需要进行调整,但我会将其留作练习。)

CREATE TABLE #Results
(
object_name nvarchar(500),
column_name  nvarchar(500)
)

exec sys.sp_MSforeachtable '
IF EXISTS(
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(''?'') AND is_nullable=1)
BEGIN
RAISERROR(''Processing ?'',0,1) WITH NOWAIT


DECLARE @ColList nvarchar(max)
DECLARE @CountList nvarchar(max)

SELECT @ColList = ISNULL(@ColList + '','','''') + QUOTENAME(name),
       @CountList = ISNULL(@CountList + '','','''') + ''COUNT(*) 
          - COUNT(CASE WHEN '' + QUOTENAME(name) + '' IS NOT NULL THEN 1 END) AS '' + QUOTENAME(name)
FROM sys.columns WHERE object_id = OBJECT_ID(''?'')  AND is_nullable=1 

DECLARE @dynsql nvarchar(max)

SET @dynsql = ''
WITH T AS
(
SELECT 
        ''''?'''' AS table_name, 
        '' + @CountList + ''
FROM ?
)
INSERT INTO #Results
SELECT  table_name, col
FROM T
UNPIVOT (NullCount FOR col IN ('' + @ColList + '')) AS UnPvt
WHERE NullCount = 0
''

EXEC(@dynsql)
END
'


SELECT *
FROM #Results

DROP TABLE #Results
Run Code Online (Sandbox Code Playgroud)