如何判断列是否为 sysname 类型

How to tell whether a column is of sysname type

常见问题是如何通过查询系统列来查找 table 中的列。例如 SQL server query to get the list of columns in a table along with Data types, NOT NULL, and PRIMARY KEY constraints 给出了在大多数情况下都有效的查询。但是,sysname 类型的列返回为普通 nvarchar。在 Management Studio (SSMS) 中编写 table 定义的脚本将正确给出 sysname 类型。 sp_columns 也会如此。但是,如何使用针对系统 table 的 SQL 查询来确定列是否属于 sysname 类型? (我不想为每个 table 分别 运行 sp_columns。)

如果您想知道 sysname 类型的开头,What is SYSNAME data type in SQL Server? 提供了一些信息。

要提供更多详细信息:

create view some_table_names as select name from sys.tables

然后运行宁

sp_columns 'some_table_names'

报告 type_name=sysname。但是针对 sys.columns 的简单查询只给出 varchar:

select type_name(c.system_type_id)
from sys.objects t
join sys.columns c
  on t.object_id = c.object_id
where t.name = 'some_table_names'

我查看了 sp_columns 的定义,看看我是否可以做同样的事情。它在系统 table sys.spt_columns_odbc_view 中查找列详细信息。但这显然是一些内部最高机密 table,只能从直接管理员连接 (DAC) 或 SSMS 查询。 (参见 What is spt_columns_odbc_view and why is it not accessible?sp_columns 过程设法查询此视图,即使我不是从 Management Studio 或 DAC 运行 中查询它。但是我不知道如何在我自己的代码中重复这个技巧。

是否有其他方法可以判断列是否为 sysname 类型?

首先,没有将数据存储为 sysname 的有效案例,即使对于维护脚本也是如此。对于脚本,您需要 table 或列的实际名称,因此将其存储在 nvarchar(128) 字段中非常合适。

系统本身将sysname视为sys.typestable中的用户类型。如果你检查记录,你会看到数据库本身告诉你这是一个 nvarchar。如果你想return那个别名,加入sys.columns.user_type_id列和types.user_type_id,例如:

select object_name(object_id), 
types.name,
* 
from sys.columns
inner join sys.types on types.user_type_id =sys.columns.user_type_id
where columns.user_type_id=256

select object_name(object_id), 
TYPE_NAME(user_type_id),
* 
from sys.columns
where user_type_id=256

更新

我刚刚在服务器上检查了类型的记录,我在服务器上使用不同的排序规则,发现排序规则发生了变化以匹配数据库的。因此,即使在同一台服务器上,使用该别名也会导致排序规则问题

sys.types 目录视图公开了可以在 DDL 中指定的数据类型。您可以在 user_type_id 上加入此视图以识别列类型。从这个查询中可以看出,sysname 不是内部机密类型。

SELECT c.Name AS ColumnName, ty.name AS TypeName, c.max_length AS ColumnLengthBytes
FROM sys.objects t
JOIN sys.columns c ON t.object_id = c.object_id 
JOIN sys.types ty ON c.user_type_id = ty.user_type_id
WHERE t.name = N'test_table';

sysname类似于用户自定义类型。它不同于使用 CREATE TYPE 创建的 UDT,因为 sys.typesis_user_defined 列将是零而不是一,因为它是由 SQL 服务器而不是用户定义的。

也可以在 system_type_id 上加入 return 用户和基本系统类型。

SELECT c.Name AS ColumnName, ty.name AS TypeName, c.max_length AS ColumnLengthBytes
FROM sys.objects t
JOIN sys.columns c ON t.object_id = c.object_id 
JOIN sys.types ty ON ty.system_type_id = c.system_type_id
WHERE t.name = N'test_table';