SQL Server 中的 SYSNAME 数据类型是啥?
Posted
技术标签:
【中文标题】SQL Server 中的 SYSNAME 数据类型是啥?【英文标题】:What is SYSNAME data type in SQL Server?SQL Server 中的 SYSNAME 数据类型是什么? 【发布时间】:2011-08-08 21:04:49 【问题描述】:SQL Server SYSNAME 数据类型有什么用途? BOL 说:
sysname 数据类型用于 表列、变量和存储 存储对象的过程参数 名字。
但我真的不明白。有没有可以提供的用例?
【问题讨论】:
除了下面这些很好的答案之外,它还用于对尝试使用 sys.types 获取列元数据的人造成严重破坏,因为它与 nvarchar 共享相同的 system_type_id。 【参考方案1】:sysname
是一种内置数据类型,限制为 128 个 Unicode 字符,IIRC 主要用于在创建脚本时存储对象名称。它的值不能是NULL
和使用nvarchar(128) NOT NULL
基本一样
编辑
正如@Jim 在 cmets 中提到的,老实说,我认为没有真正的商业案例可以使用sysname
。主要用于微软在SQL Server内部构建sys
表和存储过程等。
例如,通过执行Exec sp_help 'sys.tables'
你会看到name
这个列被定义为sysname
这是因为this的值本身就是一个对象(一个表)
我不会太担心。
还值得注意的是,对于那些仍在使用 SQL Server 6.5 及更低版本的人(还有人在使用它吗?)sysname
的内置类型相当于varchar(30)
文档
sysname
是用 nchar
and nvarchar
的文档定义的,在备注部分:
sysname 是系统提供的用户定义数据类型,在功能上等同于 nvarchar(128),但它不能为空。 sysname 用于引用数据库对象名称。
为了澄清上述说明,默认 sysname 定义为NOT NULL
,当然可以将其定义为可为空的。同样重要的是要注意,SQL Server 实例之间的确切定义可能会有所不同。
Using Special Data Types
sysname 数据类型用于表列、变量和存储 存储对象名称的过程参数。的确切定义 sysname 与标识符的规则有关。因此,它可以 SQL Server 实例之间的差异。 sysname 功能相同 与 nvarchar(128) 相同,但默认情况下 sysname 不为 NULL。在 较早版本的 SQL Server,sysname 定义为 varchar(30)。
有关sysname
允许或禁止NULL
值的更多信息,请参见https://***.com/a/52290792/300863
仅仅因为它是默认值(不为空)并不能保证它会是!
【讨论】:
"有没有可以提供的用例?"我认为您不会找到使用的实际商业理由。它主要在 MS SQL 内部使用,因为它可能在表等中使用得相当多。 您可以在脚本中使用sysname
来实现向前(和向后)兼容性。
只需在此处投入 2 美分:将我带到这里的列在 SP 中声明为 nvarchar(max)
不为空,但它们在 sys 表中显示为 sysname
。
@Barry 实际上...根据sys.types
是nvarchar(256) not null
。请注意,系统类型 ID = 231 (nvarchar)。现在它在 TDS 中用作类型别名;别名的第一个ID是256,对应sysname
。至于用法:sysname
用于信息模式。
@atlaste sys.tables 中的 max_length 长度以字节为单位。 nvarchar 每个字符使用两个字节,这就是它定义为 nvarchar(128) 的原因。【参考方案2】:
有没有可以提供的用例?
如果您需要创建一些dynamic sql,则可以使用sysname
作为保存表名、列名和服务器名的变量的数据类型。
【讨论】:
【参考方案3】:仅供参考....
select * from sys.types where system_type_id = 231
给你两行。
(我还不确定这意味着什么,但我 100% 确定它现在正在弄乱我的代码)
编辑:我猜这意味着你应该在这种情况下(我的情况)加入 user_type_id 或者可能同时加入 user_type_id 和 system_type_id
name system_type_id user_type_id schema_id principal_id max_length precision scale collation_name is_nullable is_user_defined is_assembly_type default_object_id rule_object_id
nvarchar 231 231 4 NULL 8000 0 0 SQL_Latin1_General_CP1_CI_AS 1 0 0 0 0
sysname 231 256 4 NULL 256 0 0 SQL_Latin1_General_CP1_CI_AS 0 0 0 0 0
create procedure dbo.yyy_test (
@col_one nvarchar(max),
@col_two nvarchar(max) = 'default',
@col_three nvarchar(1),
@col_four nvarchar(1) = 'default',
@col_five nvarchar(128),
@col_six nvarchar(128) = 'default',
@col_seven sysname
)
as begin
select 1
end
此查询:
select parm.name AS Parameter,
parm.max_length,
parm.parameter_id
from sys.procedures sp
join sys.parameters parm ON sp.object_id = parm.object_id
where sp.name = 'yyy_test'
order by parm.parameter_id
产量:
parameter max_length parameter_id
@col_one -1 1
@col_two -1 2
@col_three 2 3
@col_four 2 4
@col_five 256 5
@col_six 256 6
@col_seven 256 7
还有这个:
select parm.name as parameter,
parm.max_length,
parm.parameter_id,
typ.name as data_type,
typ.system_type_id,
typ.user_type_id,
typ.collation_name,
typ.is_nullable
from sys.procedures sp
join sys.parameters parm ON sp.object_id = parm.object_id
join sys.types typ ON parm.system_type_id = typ.system_type_id
where sp.name = 'yyy_test'
order by parm.parameter_id
给你这个:
parameter max_length parameter_id data_type system_type_id user_type_id collation_name is_nullable
@col_one -1 1 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_one -1 1 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
@col_two -1 2 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_two -1 2 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
@col_three 2 3 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_three 2 3 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
@col_four 2 4 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_four 2 4 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
@col_five 256 5 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_five 256 5 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
@col_six 256 6 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_six 256 6 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
@col_seven 256 7 nvarchar 231 231 SQL_Latin1_General_CP1_CI_AS 1
@col_seven 256 7 sysname 231 256 SQL_Latin1_General_CP1_CI_AS 0
【讨论】:
sys.types
也包含您创建的 user defined types。如果你做create type MyInt from int
,你将有两行system_type_id = 56
。另一个默认重复的是 240,它是 hierarchyid、geometry 和 geography 的系统类型。
我完全忘记了这一点。那么......用其中的系统名查询这些东西的理想方法是什么?因为它是一个“别名”,我可以只做where typ.name<>'sysname'
还是会产生一些我不知道的其他后果?
在 system_type_id 和 user_type_id 上加入 sys.types。 SQL Fiddle
哦,这就是我在最上面所说的。我以为你说的不对……
对不起,不是我的意思。只是想指出一些其他可能会弄乱您的查询的事情,不仅 sysname 可能会在不加入两列的情况下让您感到悲伤。【参考方案4】:
让我在下面列出一个用例。希望能帮助到你。在这里,我试图从数据库“学生”中找到表“Stud_dtls”的表所有者。正如 Mikael 所提到的,当需要创建一些需要保存表名、列名和服务器名的变量的动态 sql 时,可以使用 sysname。只是想提供一个简单的例子来补充他的观点。
USE Students
DECLARE @TABLE_NAME sysname
SELECT @TABLE_NAME = 'Stud_dtls'
SELECT TABLE_SCHEMA
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME = @TABLE_NAME
【讨论】:
【参考方案5】:sysname
由 sp_send_dbmail
使用,这是一个“向指定收件人发送电子邮件”的存储过程,位于 msdb 数据库中。
根据Microsoft,
[ @profile_name = ] 'profile_name'
是从中发送消息的配置文件的名称。 profile_name 是 sysname 类型,带有 默认为 NULL。 profile_name 必须是现有的名称 数据库邮件配置文件。当没有指定 profile_name 时, sp_send_dbmail 使用当前用户的默认专用配置文件。 如果用户没有默认的私人配置文件,sp_send_dbmail 使用 msdb 数据库的默认公共配置文件。如果用户 没有默认的私人档案,也没有默认的公共档案 数据库的配置文件,必须指定@profile_name。
【讨论】:
【参考方案6】:FWIW,如果您希望以这种方式探索数据库,您可以像这样将表名传递给有用的系统 SP:
DECLARE @Table sysname; SET @Table = 'TableName';
EXEC sp_fkeys @Table;
EXEC sp_help @Table;
【讨论】:
【参考方案7】:另一个用例是使用 AT TIME ZONE
的 SQL Server 2016+ 功能时
以下语句将返回转换为 GMT 的日期
SELECT
CONVERT(DATETIME, SWITCHOFFSET([ColumnA], DATEPART(TZOFFSET, [ColumnA] AT TIME ZONE 'GMT Standard Time')))
如果您想将时区作为变量传递,请说:
SELECT
CONVERT(DATETIME, SWITCHOFFSET([ColumnA], DATEPART(TZOFFSET, [ColumnA] AT TIME ZONE @TimeZone)))
那么该变量需要是sysname
类型(将其声明为varchar
会导致错误)。
【讨论】:
【参考方案8】:有没有可以提供的用例?
您想要存储对象名称以供数据库维护脚本使用的任何位置。例如,脚本会从某些具有日期列的表中清除旧行。它配置了一个表,该表提供表名、要过滤的列名以及要保留多少天的历史记录。另一个脚本将某些表转储到 CSV 文件,并再次配置一个列出要转储的表的表。这些配置表可以使用sysname
类型来存储表名和列名。
【讨论】:
你根本不需要那个。只需使用nvarchar(128) not null
列。名字就是这样,一个名字。不一定非要使用sysname
当然,事实上它甚至不必是那种类型,nvarchar(300)
也可以工作,或者甚至只是varchar
如果你不在表名中使用 Unicode(因为我'确信几乎没有人这样做)。 sysname
的优势部分在于它使意图更清晰:此列包含对象名称;部分原因是即使您迁移到不同版本的 MSSQL 更改了用于对象名称的数据类型(就像以前发生的那样),它仍将是正确的类型。
不,它没有。它只是映射到nvarchar(128) NOT NULL
的另一种用户类型(本质上是别名)。事实上,这就是您可以通过检查user_type_id
列的值来找到类型的方法。与创建自己的用户类型相比,使用该类型获得的收益没有更多
你的意思是如果sysname
的定义在较新的MSSQL版本中被更改,并且数据库被备份并恢复到较新的实例中,那么之前所有的列是sysname
现在将是错误的类型并且不再匹配系统表中使用的类型?
不可能,或者更糟的是,如果发生这种情况,您的色谱柱就会被水洗。 sysname
是用户定义的类型,usert_type_id
256。没有 ALTER TYPE
所以没有办法改变它。您必须创建一个新类型并将所有使用旧类型的列更改为新类型。如果 MS 决定更改此 他们 必须将现有系统表数据迁移到新类型。您可以期望他们为他们已经知道的系统表执行此操作,但是任何 user 表都必须由用户迁移以上是关于SQL Server 中的 SYSNAME 数据类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章