【问题标题】:Retrieving datalength along with columns and tables in SQL Server query在 SQL Server 查询中检索数据长度以及列和表
【发布时间】:2019-03-09 09:25:14
【问题描述】:

因为我想将列转换为不是varchar(MAX) 我想查看每列的最大数据长度来决定新的大小应该是多少。

我有这个查询来查找我所有的(n)varchar(MAX) 列。

SELECT [TABLE_NAME], [COLUMN_NAME]
FROM information_schema.columns
WHERE DATA_TYPE IN ('varchar', 'nvarchar')
  AND CHARACTER_MAXIMUM_LENGTH = -1
ORDER BY TABLE_NAME, COLUMN_NAME

例如,我有一个客户表,在结果中,以下是我的客户表的输出

+------------+--------------+
| TABLE_NAME | COLUMN_NAME  |
+------------+--------------+
| customers  | name         |
| customers  | address      |
| customers  | postal_code  |
| customers  | city         |
| customers  | email        |
| customers  | phone_number |
+------------+--------------+

通过运行以下查询:

SELECT MAX(DATALENGTH(name)) FROM customers
SELECT MAX(DATALENGTH(address)) FROM customers
SELECT MAX(DATALENGTH(postal_code)) FROM customers
SELECT MAX(DATALENGTH(city)) FROM customers
SELECT MAX(DATALENGTH(email)) FROM customers
SELECT MAX(DATALENGTH(phone_number)) FROM customers

我可以得到我想要的结果,但我真的希望它只是一个返回如下内容的查询:

+------------+--------------+------------+
| TABLE_NAME | COLUMN_NAME  | Datalength |
+------------+--------------+------------+
| customers  | name         |         93 |
| customers  | address      |        122 |
| customers  | postal_code  |          6 |
| customers  | city         |         44 |
| customers  | email        |         75 |
| customers  | phone_number |         18 |
+------------+--------------+------------+

我试过了

SELECT 
    [TABLE_NAME], [COLUMN_NAME], 
    (SELECT MAX(DATALENGTH(COLUMN_NAME))
     FROM TABLE_NAME) AS 'MaxContentLength'
FROM information_schema.columns
WHERE DATA_TYPE IN ('varchar', 'nvarchar')
  AND CHARACTER_MAXIMUM_LENGTH = -1
ORDER BY TABLE_NAME, COLUMN_NAME

但我收到此错误:

消息 208,第 16 级,状态 1,第 1 行
无效的对象名称“TABLE_NAME”

我该如何解决这个问题(或者有其他方法可以做我想做的事吗?)

【问题讨论】:

  • Table_name 不是一个表,它是一个列。您不能在子查询中执行此操作。
  • 根据documentation,对于 xml 和大值类型数据,CHARACTER_MAXIMUM_LENGTH 为 -1。那么,您是否试图获得 XML 类型的最大可能长度?或者是其他东西?对于 xml,它通常是 2GB。 ref
  • @LukStorms 我已经更新了我的问题,以便更清楚地说明我在寻找什么

标签: sql sql-server max information-schema datalength


【解决方案1】:

这是我解决您问题的方法,可能不是最快的。

declare @tbl varchar(128), @fld varchar(128)
declare @res table (
    [Table_Name] varchar(128), [Column_Name] varchar(128), [DataLength] int)

declare c1 cursor local for
    select c.TABLE_NAME, c.COLUMN_NAME
    from INFORMATION_SCHEMA.COLUMNS c
    join INFORMATION_SCHEMA.TABLES t on 
        (t.TABLE_CATALOG = c.TABLE_CATALOG and 
         t.TABLE_SCHEMA = c.TABLE_SCHEMA and 
         t.TABLE_NAME = c.TABLE_NAME)
    where t.TABLE_TYPE <> 'VIEW' 
        and c.DATA_TYPE in ('varchar', 'nvarchar') 
        and c.CHARACTER_MAXIMUM_LENGTH = -1
open c1
fetch next from c1 into @tbl, @fld
while @@FETCH_STATUS=0
begin
    insert into @res
    exec ('select '''
          +@tbl+''' as [TABLE_NAME], '''
          +@fld+''' as [COLUMN_NAME], max(datalength('
          +@fld+')) as [DataLength] from '
          +@tbl)
    fetch next from c1 into @tbl, @fld
end    
close c1
deallocate c1

select * from @res

【讨论】:

    【解决方案2】:

    这对你来说正确吗?

    SELECT 
        I.TABLE_NAME, I.COLUMN_NAME, 
        (SELECT MAX(DATALENGTH(COLUMN_NAME))
         FROM information_schema.columns
         WHERE TABLE_NAME = I.TABLE_NAME) AS 'MaxContentLength'
    FROM information_schema.columns AS I
    WHERE I.DATA_TYPE IN ('varchar', 'nvarchar')
      AND CHARACTER_MAXIMUM_LENGTH = -1
    ORDER BY I.TABLE_NAME, I.COLUMN_NAME
    

    【讨论】:

      【解决方案3】:

      使用DATALENGTH 的多个查询可以合并为一个。

      未经测试的记事本涂鸦

      SELECT 
       [TABLE_NAME], 
       [COLUMN_NAME], 
       [Datalength]
      FROM 
      (
          SELECT 
           'customers' AS [TABLE_NAME], 
           MAX(DATALENGTH(name)) AS name,
           MAX(DATALENGTH(address)) AS address,  
           MAX(DATALENGTH(postal_code)) AS postal_code,
           MAX(DATALENGTH(city)) AS city,
           MAX(DATALENGTH(email)) AS email,
           MAX(DATALENGTH(phone_number)) AS phone_number
          FROM customers
      ) AS src
      UNPIVOT  
      (
        [Datalength] 
        FOR [COLUMN_NAME] IN   
        ([name], [address], [postal_code], [city], [email], [phone_number])  
      ) AS unpvt; 
      

      【讨论】:

      • 这对于我的问题中的 6 个示例来说很好,但我在数百个表中有数千列。至少我需要自动生成这种格式的查询才能工作
      • 好吧,使用 information_schema 表可以通过动态 Sql 生成这种查询,但仅限于 1 个表。并且可以在以表名作为参数的过程中生成和执行该动态 Sql。但是 1 次查询可以一次获取所有这些表的所有长度,这将是一个 SQL 的怪物。
      • 基于information_schemahere使用Dynamic Sql的一个例子
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      • 2023-03-31
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多