我創建了一個存儲過程來解決這個問題。它使用INFORMATION_SCHEMA
找到IDENTITY
列,然後使用IDENT_CURRENT
和列的DATA_TYPE
來計算完整百分比。指定數據庫作爲第一個參數,然後選擇最小百分比和數據類型。
EXEC master.dbo.CheckIdentityColumns 'MyDatabase' --all
EXEC master.dbo.CheckIdentityColumns 'MyDatabase', 50 --columns 50% full or greater
EXEC master.dbo.CheckIdentityColumns 'MyDatabase', 50, 'int' --only int columns
輸出示例:
Table Column Type Percent Full Remaining
------------------------- ------------------ ------- ------------ ---------------
MyDatabase.dbo.Table1 Table1ID int 9 1,937,868,393
MyDatabase.dbo.Table2 Table2ID int 5 2,019,944,894
MyDatabase.dbo.Table3 Table3ID int 9 1,943,793,775
我創建了一個提醒,檢查我所有的數據庫,每月一次,我登錄電子表格信息。
CheckIdentityColumns程序
USE master
GO
CREATE PROCEDURE dbo.CheckIdentityColumns
(
@Database AS NVARCHAR(128),
@PercentFull AS TINYINT = 0,
@Type AS VARCHAR(8) = NULL
)
AS
--this procedure assumes you are not using negative numbers in your identity columns
DECLARE @Sql NVARCHAR(3000)
SET @Sql =
'USE ' + @Database + '
SELECT
[Column].TABLE_CATALOG + ''.'' +
[Column].TABLE_SCHEMA + ''.'' +
[Table].TABLE_NAME AS [Table],
[Column].COLUMN_NAME AS [Column],
[Column].DATA_TYPE AS [Type],
CAST((
CASE LOWER([Column].DATA_TYPE)
WHEN ''tinyint''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/255)
WHEN ''smallint''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/32767)
WHEN ''int''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/2147483647)
WHEN ''bigint''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/9223372036854775807)
WHEN ''decimal''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/(([Column].NUMERIC_PRECISION * 10) - 1))
END * 100) AS INT) AS [Percent Full],
REPLACE(CONVERT(VARCHAR(19), CAST(
CASE LOWER([Column].DATA_TYPE)
WHEN ''tinyint''
THEN (255 - IDENT_CURRENT([Table].TABLE_NAME))
WHEN ''smallint''
THEN (32767 - IDENT_CURRENT([Table].TABLE_NAME))
WHEN ''int''
THEN (2147483647 - IDENT_CURRENT([Table].TABLE_NAME))
WHEN ''bigint''
THEN (9223372036854775807 - IDENT_CURRENT([Table].TABLE_NAME))
WHEN ''decimal''
THEN ((([Column].NUMERIC_PRECISION * 10) - 1) - IDENT_CURRENT([Table].TABLE_NAME))
END
AS MONEY) , 1), ''.00'', '''') AS Remaining
FROM
INFORMATION_SCHEMA.COLUMNS AS [Column]
INNER JOIN
INFORMATION_SCHEMA.TABLES AS [Table]
ON [Table].TABLE_NAME = [Column].TABLE_NAME
WHERE
COLUMNPROPERTY(
OBJECT_ID([Column].TABLE_NAME),
[Column].COLUMN_NAME, ''IsIdentity'') = 1 --true
AND [Table].TABLE_TYPE = ''Base Table''
AND [Table].TABLE_NAME NOT LIKE ''dt%''
AND [Table].TABLE_NAME NOT LIKE ''MS%''
AND [Table].TABLE_NAME NOT LIKE ''syncobj_%''
AND CAST(
(
CASE LOWER([Column].DATA_TYPE)
WHEN ''tinyint''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/255)
WHEN ''smallint''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/32767)
WHEN ''int''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/2147483647)
WHEN ''bigint''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/9223372036854775807)
WHEN ''decimal''
THEN (IDENT_CURRENT([Table].TABLE_NAME)/(([Column].NUMERIC_PRECISION * 10) - 1))
END * 100
) AS INT) >= ' + CAST(@PercentFull AS VARCHAR(4))
IF (@Type IS NOT NULL)
SET @Sql = @Sql + 'AND LOWER([Column].DATA_TYPE) = ''' + LOWER(@Type) + ''''
SET @Sql = @Sql + '
ORDER BY
[Column].TABLE_CATALOG + ''.'' +
[Column].TABLE_SCHEMA + ''.'' +
[Table].TABLE_NAME,
[Column].COLUMN_NAME'
EXECUTE sp_executesql @Sql
GO
[這裏](http://meta.stackexchange.com/questions/17463/can-i-answer-my-own-questions-even-those-where-i-knew-the-answer-之前 - 問)和[這裏](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/)是爲什麼。根據SO常見問題解答,這種行爲不僅可以接受,而且是受到鼓勵的。我將繼續這樣做,直到SO社區被認爲是不禮貌的禮節。 – 2012-01-05 16:28:20
這不是一個答案,但你是否從0或1開始了你的身份?如果是,那麼您是否考慮將身份重置爲最小的int,而不是增加列大小?這會給你額外的20億列相同的大小。 – 2012-01-05 16:18:24
@AlexKuznetsov:是的,我考慮過了。我可能會在未來的項目中使用負值,但爲這個數據庫編寫的代碼太多了,我不想冒這個風險。 – 2012-01-05 16:23:21