I've the following statement that returns me the current identity values for one database
;WITH cte
AS
(SELECT
A.TABLE_CATALOG AS CATALOG
,A.TABLE_SCHEMA AS "SCHEMA"
,A.TABLE_NAME AS "TABLE"
,B.COLUMN_NAME AS "COLUMN"
,IDENT_SEED(A.TABLE_SCHEMA + '.' + A.TABLE_NAME) AS SEED
,IDENT_INCR(A.TABLE_SCHEMA + '.' + A.TABLE_NAME) AS INCREMENT
,IDENT_CURRENT(A.TABLE_SCHEMA + '.' + A.TABLE_NAME) AS CURR_VALUE
,b.DATA_TYPE AS TYPE
,CASE LOWER(B.DATA_TYPE)
WHEN 'bigint' THEN IDENT_CURRENT(A.TABLE_NAME) / 9223372036854775807
WHEN 'int' THEN IDENT_CURRENT(A.TABLE_NAME) / 2147483647
WHEN 'smallint' THEN IDENT_CURRENT(A.TABLE_NAME) / 32767
WHEN 'tinyint' THEN IDENT_CURRENT(A.TABLE_NAME) / 255
END AS [RATIO]
FROM INFORMATION_SCHEMA.TABLES A
,INFORMATION_SCHEMA.columns B
WHERE A.TABLE_CATALOG = B.TABLE_CATALOG
AND A.TABLE_SCHEMA = B.TABLE_SCHEMA
AND A.TABLE_NAME = B.TABLE_NAME
AND COLUMNPROPERTY(OBJECT_ID(A.TABLE_SCHEMA + '.' + A.TABLE_NAME), B.COLUMN_NAME, 'IsIdentity') = 1
AND OBJECTPROPERTY(OBJECT_ID(A.TABLE_SCHEMA + '.' + A.TABLE_NAME), 'TableHasIdentity') = 1
AND A.TABLE_TYPE = 'BASE TABLE')
SELECT * FROM cte WHERE RATIO > @threshold
CATALOG | SCHEMA | TABLE | COLUMN | SEED | INCREMENT | CURR_VALUE | TYPE | RATIO |
---|---|---|---|---|---|---|---|---|
Database1 | dbo | TableName1 | ColumnName1 | 1 | 1 | 1118658505 | int | 0.520916 |
Database1 | dbo | TableName2 | ColumnName2 | 1 | 1 | 926923907 | int | 0.431633 |
How can I run this (or an equal) statment against all databases on the server so I get a result in one table?
| CATALOG | SCHEMA | TABLE | COLUMN | SEED | INCREMENT | CURR_VALUE | TYPE | RATIO |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| Database1 | dbo | TableName1 | ColumnName1 | 1 | 1 | 1118658505 | int | 0.520916 |
| Database1 | dbo | TableName2 | ColumnName2 | 1 | 1 | 926923907 | int | 0.431633 |
| Database2 | dbo | TableName3 | ColumnName3 | 1 | 1 | 401894827 | int | 0.187146 |
| Database2 | dbo | TableName4 | ColumnName4 | 1 | 1 | 756925871 | int | 0.352471 |
I've tried to use USE [<DATABASE_NAME>]
but would need dynamic SQL and would also receive multiple return sets instead of one.
Any ideas?
2条答案
按热度按时间uhry853o1#
You can do something like this:
It builds dynamic sql string which unions all databases and executes it once.
I simplified the usage of views so you use something a bit more modern, but you can probably adapt your original script from the general idea.
l2osamch2#
The query itself can be simplified a lot by querying the sys.identity_columns system view, which already contains table, column, last value, seed and even size information in bytes, in the form of the
max_length
columnFor example :
The maximum size is generated by raising 2 to the number of bits.
max_length*7
is used instead ofmax_length*8
because the question seems to only count positive ID values. Nothing prevents negative ID values though.seed_value
,increment_value
andlast_value
are asql_variant
columns that must be cast to a numeric type before they're used in calculations.This query can be executed against all databases using the undocumented but globally (as in used by everyone,everywhere)
sp_MSForEachDB
stored procedureThis produces multiple result sets. These can be inserted into a temporary table or table variable:
All this can be wrapped into a stored procedure that returns rows that exceed the ratio:
And called with the ratio as a parameter: