如何检查 SQL 服务器中的实际列数据类型
How can I check actual column datatype in SQL Server
我想检查数据库中所有列的实际数据类型,并将结果与 table information_schema.columns 进行比较。目的是检测超大列数据类型以减少它。
例如,如果列定义为 varchar(255)
但所有值都只有 10 个字符或更少,我希望在结果中看到它。
我知道这个查询是为了获取每一列的信息:
SELECT *
FROM information_schema.columns
WHERE table_schema = 'dbo'
ORDER BY TABLE_NAME, ORDINAL_POSITION
有人知道如何计算任何数据类型的最大值并将其与设置进行比较吗?
示例示例:
| ColA (varchar255)| ColB (nvarchar255) |
| -------- | -------------- |
| First | first row |
| Second | row 2 |
| Third | a row |
预期结果:
| Col | type len | actual max len |
| -------- | -------------- | -------------- |
| ColA | 255 | 6 |
| ColB | 255 | 9 |
下面的脚本对每个 variable-length 列执行 MAX DATALENGTH 查询以确定实际的最大大小(以字节为单位)并列出结果以及定义的最大大小。此版本使用 SQL 服务器系统目录视图而不是 INFORMATION_SCHEMA
。
请注意,如果您的数据库很大并且会影响性能,这可能需要一些时间。如果您 运行 针对没有 RCSI 的活动数据库,考虑 READ_UNCOMMITTED
并理解结果可能不那么准确。
SET NOCOUNT ON;
DECLARE @results TABLE(
SchemaName sysname NOT NULL
,TableName sysname NOT NULL
,ColumnName sysname NOT NULL
,DefinedMaxLength int NOT NULL
,ActualMaxLength int NULL
);
DECLARE
@SchemaName sysname
,@TableName sysname
,@ColumnName sysname
,@DefinedMaxLength int
,@ActualMaxLength int
,@MaxLengthQuery nvarchar(MAX);
DECLARE MaxColumnSizes CURSOR LOCAL FAST_FORWARD FOR
SELECT
OBJECT_SCHEMA_NAME(t.object_id) AS SchemaName
,OBJECT_NAME(t.object_id) AS TableName
,c.name AS ColumnName
,CASE WHEN c.max_length = -1 THEN 2147483647 ELSE c.max_length END AS DefinedMaxMength
,N'SELECT @ActualMaxLength = MAX(DATALENGTH(' + c.name + N'))'
+ N' FROM ' + QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + N'.' + QUOTENAME(OBJECT_NAME(t.object_id)) AS MaxLengthQuery
FROM sys.tables AS t
JOIN sys.columns AS c ON c.object_id = t.object_id
JOIN sys.types AS ty ON ty.system_type_id = c.system_type_id AND ty.system_type_id = c.user_type_id
WHERE
ty.name IN(N'varchar', 'nvarchar', N'varbinary')
AND OBJECTPROPERTY(t.object_id, 'IsMSShipped') = 0;
OPEN MaxColumnSizes;
WHILE 1 = 1
BEGIN
FETCH NEXT FROM MaxColumnSizes INTO
@SchemaName
,@TableName
,@ColumnName
,@DefinedMaxLength
,@MaxLengthQuery;
IF @@FETCH_STATUS = -1 BREAK;
--PRINT @MaxLengthQuery; --for debugging
SET @ActualMaxLength = NULL;
EXEC sp_executesql @MaxLengthQuery, N'@ActualMaxLength int OUTPUT', @ActualMaxLength = @ActualMaxLength OUTPUT;
INSERT INTO @results (SchemaName, TableName, ColumnName, DefinedMaxLength, ActualMaxLength)
VALUES(@SchemaName, @TableName, @ColumnName, @DefinedMaxLength, @ActualMaxLength);
END;
CLOSE MaxColumnSizes;
DEALLOCATE MaxColumnSizes;
SELECT
SchemaName
,TableName
,ColumnName
,DefinedMaxLength
,ActualMaxLength
FROM @results
ORDER BY
SchemaName
,TableName
,ColumnName;
GO
我想检查数据库中所有列的实际数据类型,并将结果与 table information_schema.columns 进行比较。目的是检测超大列数据类型以减少它。
例如,如果列定义为 varchar(255)
但所有值都只有 10 个字符或更少,我希望在结果中看到它。
我知道这个查询是为了获取每一列的信息:
SELECT *
FROM information_schema.columns
WHERE table_schema = 'dbo'
ORDER BY TABLE_NAME, ORDINAL_POSITION
有人知道如何计算任何数据类型的最大值并将其与设置进行比较吗?
示例示例:
| ColA (varchar255)| ColB (nvarchar255) |
| -------- | -------------- |
| First | first row |
| Second | row 2 |
| Third | a row |
预期结果:
| Col | type len | actual max len |
| -------- | -------------- | -------------- |
| ColA | 255 | 6 |
| ColB | 255 | 9 |
下面的脚本对每个 variable-length 列执行 MAX DATALENGTH 查询以确定实际的最大大小(以字节为单位)并列出结果以及定义的最大大小。此版本使用 SQL 服务器系统目录视图而不是 INFORMATION_SCHEMA
。
请注意,如果您的数据库很大并且会影响性能,这可能需要一些时间。如果您 运行 针对没有 RCSI 的活动数据库,考虑 READ_UNCOMMITTED
并理解结果可能不那么准确。
SET NOCOUNT ON;
DECLARE @results TABLE(
SchemaName sysname NOT NULL
,TableName sysname NOT NULL
,ColumnName sysname NOT NULL
,DefinedMaxLength int NOT NULL
,ActualMaxLength int NULL
);
DECLARE
@SchemaName sysname
,@TableName sysname
,@ColumnName sysname
,@DefinedMaxLength int
,@ActualMaxLength int
,@MaxLengthQuery nvarchar(MAX);
DECLARE MaxColumnSizes CURSOR LOCAL FAST_FORWARD FOR
SELECT
OBJECT_SCHEMA_NAME(t.object_id) AS SchemaName
,OBJECT_NAME(t.object_id) AS TableName
,c.name AS ColumnName
,CASE WHEN c.max_length = -1 THEN 2147483647 ELSE c.max_length END AS DefinedMaxMength
,N'SELECT @ActualMaxLength = MAX(DATALENGTH(' + c.name + N'))'
+ N' FROM ' + QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + N'.' + QUOTENAME(OBJECT_NAME(t.object_id)) AS MaxLengthQuery
FROM sys.tables AS t
JOIN sys.columns AS c ON c.object_id = t.object_id
JOIN sys.types AS ty ON ty.system_type_id = c.system_type_id AND ty.system_type_id = c.user_type_id
WHERE
ty.name IN(N'varchar', 'nvarchar', N'varbinary')
AND OBJECTPROPERTY(t.object_id, 'IsMSShipped') = 0;
OPEN MaxColumnSizes;
WHILE 1 = 1
BEGIN
FETCH NEXT FROM MaxColumnSizes INTO
@SchemaName
,@TableName
,@ColumnName
,@DefinedMaxLength
,@MaxLengthQuery;
IF @@FETCH_STATUS = -1 BREAK;
--PRINT @MaxLengthQuery; --for debugging
SET @ActualMaxLength = NULL;
EXEC sp_executesql @MaxLengthQuery, N'@ActualMaxLength int OUTPUT', @ActualMaxLength = @ActualMaxLength OUTPUT;
INSERT INTO @results (SchemaName, TableName, ColumnName, DefinedMaxLength, ActualMaxLength)
VALUES(@SchemaName, @TableName, @ColumnName, @DefinedMaxLength, @ActualMaxLength);
END;
CLOSE MaxColumnSizes;
DEALLOCATE MaxColumnSizes;
SELECT
SchemaName
,TableName
,ColumnName
,DefinedMaxLength
,ActualMaxLength
FROM @results
ORDER BY
SchemaName
,TableName
,ColumnName;
GO