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.typesnvarchar(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】:

sysnamesp_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 数据类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章

SQL远程连接

实现Sql server数据库的远程连接访问

Sql Server 给表及字段添加注释

如何查看sql server 2012是不是激活?在哪里查看?急求呀

SQL Server 2008中的9种数据挖掘算法

SQL Server中的游标CURSOR