0

It's a common question how to find the columns in a table by querying the system columns. For example SQL server query to get the list of columns in a table along with Data types, NOT NULL, and PRIMARY KEY constraints gives a query which works in most cases. However, a column of type sysname is returned as plain nvarchar. In Management Studio (SSMS) scripting out a table definition will correctly give the sysname type. And so will sp_columns. But how can I find whether a column is of sysname type using an SQL query against the system tables? (I don't want to run sp_columns separately for each table.)

In case you are wondering what the sysname type is to start with, What is SYSNAME data type in SQL Server? gives some info.

To give more detail:

create view some_table_names as select name from sys.tables

Then running

sp_columns 'some_table_names'

reports type_name=sysname. But a simple query against sys.columns gives just 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'

I had a look at the definition of sp_columns to see if I could do the same thing. It looks up the column details in a system table sys.spt_columns_odbc_view. But this is apparently some top secret internal table that can only be queried from a direct administrator connection (DAC) or from SSMS. (See What is spt_columns_odbc_view and why is it not accessible?) The sp_columns proc manages to query this view even though I am not running it from Management Studio or over a DAC. But I don't know how to repeat that trick in my own code.

Is there some other way to tell whether a column is of sysname type?

4

2 回答 2

1

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

系统本身将表sysname中的用户类型视为用户类型sys.types。如果您检查记录,您会看到数据库本身告诉您这是一个nvarchar. 如果要返回该别名,请使用 加入sys.columns.user_type_idtypes.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

更新

我刚刚检查了服务器上的类型记录,在该服务器上我使用不同的排序规则进行数据库化,并注意到排序规则更改为与数据库匹配。因此,即使在同一台服务器上,使用该别名也会导致排序问题

于 2020-06-03T10:24:22.177 回答
1

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类似于用户定义的类型。它与创建的 UDT 的不同之处在于CREATE TYPE, 的is_user_definedsys.types将为零而不是一,因为它是由 SQL Server 而不是用户定义的。

还可以加入system_type_id以返回用户和基本系统类型。

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';
于 2020-06-03T10:49:07.247 回答