O que é o tipo de dados SYSNAME no SQL Server?

131

Para que serve o tipo de dados SYSNAME do SQL Server? BOL diz:

O tipo de dados sysname é usado para colunas da tabela, variáveis ​​e parâmetros de procedimento armazenado que armazenam nomes de objetos.

mas eu realmente não entendo isso. Existe um caso de uso que você pode fornecer?

jrara
fonte
1
Além das respostas abaixo, também é usado para causar estragos a alguém que tenta obter metadados da coluna usando sys.types, porque compartilha o mesmo system_type_id que o nvarchar.
StingyJack 16/02

Respostas:

150

sysnameé um tipo de dados interno limitado a 128 caracteres Unicode que, IIRC, é usado principalmente para armazenar nomes de objetos ao criar scripts. Seu valor não pode serNULL

É basicamente o mesmo que usar nvarchar(128) NOT NULL

EDITAR

Como mencionado por @Jim nos comentários, não acho que exista realmente um caso de negócios em que você usaria sysnamepara ser honesto. É usado principalmente pela Microsoft ao criar systabelas internas e procedimentos armazenados, etc, no SQL Server.

Por exemplo, ao executar, Exec sp_help 'sys.tables'você verá que a coluna nameestá definida, sysnamepois o valor disso é na verdade um objeto em si (uma tabela)

Eu me preocuparia muito com isso.

Também é importante notar que, para as pessoas que ainda usam o SQL Server 6.5 e inferior (ainda existem pessoas que o usam?), O tipo incorporado sysnameé equivalente avarchar(30)

Documentação

sysnameé definido com a documentação para ncharenvarchar , na seção de comentários:

sysname é um tipo de dados definido pelo usuário fornecido pelo sistema que é funcionalmente equivalente a nvarchar (128) , exceto que não é anulável. sysname é usado para referenciar nomes de objetos de banco de dados.

Para esclarecer as observações acima, por padrão sysname é definido, NOT NULLpois certamente é possível defini-lo como nulo. Também é importante observar que a definição exata pode variar entre instâncias do SQL Server.

Usando tipos de dados especiais

O tipo de dados sysname é usado para colunas da tabela, variáveis ​​e parâmetros de procedimento armazenado que armazenam nomes de objetos. A definição exata de sysname está relacionada às regras para identificadores. Portanto, pode variar entre instâncias do SQL Server. O sysname é funcionalmente o mesmo que nvarchar (128), exceto que, por padrão, sysname NÃO é NULL. Nas versões anteriores do SQL Server, sysname é definido como varchar (30).

Algumas informações adicionais sobre como sysnamepermitir ou não NULLvalores podem ser encontradas aqui https://stackoverflow.com/a/52290792/300863

Só porque é o padrão (não ser NULL) não garante que será!

codingbadger
fonte
1
"Existe um caso de uso que você possa fornecer?" Eu não acho que você encontrará um motivo comercial prático para usá-lo. Na maior parte é usada internamente no MS SQL como é provavelmente usado um pouco em tabelas, etc.
Jim
9
Você usaria sysnamepara compatibilidade direta (e reversa) em seus scripts.
Martin Smith
apenas colocando 2 centavos aqui: as colunas que me trouxeram aqui são declaradas como nvarchar(max)não nulas no SP, mas estão sendo mostradas como a sysnamenas tabelas sys.
gloomy.penguin
3
@ Barry Na verdade ... de acordo com sys.typesé um nvarchar(256) not null. Observe que o tipo de sistema ID = 231 (nvarchar). Ele funciona como um alias de tipo no TDS atualmente; o primeiro ID de um alias é 256, o que corresponde a sysname. Quanto ao uso: sysnameé usado no esquema de informações.
Atlaste
2
@ atlaste O comprimento max_length em sys.tables está em bytes. nvarchar usa dois bytes por caractere, razão pela qual é definido como nvarchar (128).
David Rushton
60

Existe um caso de uso que você possa fornecer?

Se você precisar criar algum sql dinâmico , é apropriado usá-lo sysnamecomo tipo de dados para variáveis ​​contendo nomes de tabelas, nomes de colunas e nomes de servidores.

Mikael Eriksson
fonte
6

Assim como um FYI ....

select * from sys.types where system_type_id = 231 fornece duas linhas.

(Ainda não tenho certeza do que isso significa, mas tenho 100% de certeza que está atrapalhando meu código)

edit: eu acho que o que isso significa é que você deve participar pelo user_type_id nesta situação (minha situação) ou possivelmente pelo user_type_id e pelo thesystem_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 

Esta consulta:

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

rendimentos:

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

e isto:

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

dá a você o seguinte:

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
gloomy.penguin
fonte
sys.typesmantém os tipos definidos pelo usuário que você cria também. Se você create type MyInt from inttiver duas linhas com system_type_id = 56. Outra duplicada por padrão é 240, que é o tipo de sistema para hierarchyid, geometry e geography.
Mikael Eriksson
Eu esqueci isso completamente. Então ... qual é a maneira ideal de consultar essas coisas com o sysname lá? já que é um 'pseudônimo', posso fazer where typ.name<>'sysname'ou isso teria algum outro tipo de consequência que eu não conheço?
gloomy.penguin
3
Associe-se ao sys.types em system_type_id e user_type_id. SQL Fiddle
Mikael Eriksson
ah, foi o que eu disse no topo. Eu pensei que você estava dizendo que estava errado ...
gloomy.penguin
Desculpe por isso, não o meu significado. Só queria apontar algumas outras coisas que poderiam atrapalhar sua consulta, não apenas o sysname poderia causar luto sem se juntar às duas colunas.
Mikael Eriksson
3

Deixe-me listar um caso de uso abaixo. Espero que ajude. Aqui estou tentando encontrar o proprietário da tabela 'Stud_dtls' no banco de dados 'Students'. Como Mikael mencionou, sysname pode ser usado quando houver necessidade de criar algum sql dinâmico que precise de variáveis ​​contendo nomes de tabelas, nomes de colunas e nomes de servidores. Apenas pensei em fornecer um exemplo simples para complementar seu argumento.

USE Students

DECLARE @TABLE_NAME sysname

SELECT @TABLE_NAME = 'Stud_dtls'

SELECT TABLE_SCHEMA 
  FROM INFORMATION_SCHEMA.Tables
 WHERE TABLE_NAME = @TABLE_NAME
um ok
fonte
2

sysnameé usado por sp_send_dbmail, um procedimento armazenado que "Envia uma mensagem de email para os destinatários especificados" e localizado no banco de dados msdb.

Segundo a Microsoft ,

[ @profile_name = ] 'profile_name'  

É o nome do perfil para o qual enviar a mensagem. O profile_name é do tipo sysname, com o padrão NULL. O profile_name deve ser o nome de um perfil existente do Database Mail. Quando nenhum profile_name é especificado, sp_send_dbmail usa o perfil privado padrão para o usuário atual. Se o usuário não tiver um perfil privado padrão, sp_send_dbmail usará o perfil público padrão para o banco de dados msdb. Se o usuário não tiver um perfil privado padrão e não houver um perfil público padrão para o banco de dados, @profile_name deverá ser especificado.

usefulBee
fonte
1

FWIW, você pode passar um nome de tabela para SPs úteis do sistema como este, caso deseje explorar um banco de dados dessa maneira:

DECLARE @Table sysname; SET @Table = 'TableName';
EXEC sp_fkeys @Table;
EXEC sp_help @Table;
AjV Jsy
fonte
0

Outro caso de uso é ao usar a funcionalidade SQL Server 2016+ de AT TIME ZONE

A declaração abaixo retornará uma data convertida para GMT

SELECT 
CONVERT(DATETIME, SWITCHOFFSET([ColumnA], DATEPART(TZOFFSET, [ColumnA] AT TIME ZONE 'GMT Standard Time')))

Se você deseja passar o fuso horário como uma variável, diga:

SELECT 
CONVERT(DATETIME, SWITCHOFFSET([ColumnA], DATEPART(TZOFFSET, [ColumnA] AT TIME ZONE @TimeZone)))

então essa variável precisa ser do tipo sysname(declarando-a como varcharcausará um erro).

d219
fonte
0

Existe um caso de uso que você possa fornecer?

Em qualquer lugar que você deseja armazenar um nome de objeto para uso pelos scripts de manutenção do banco de dados. Por exemplo, um script limpa linhas antigas de determinadas tabelas que possuem uma coluna de data. Ele é configurado com uma tabela que fornece o nome da tabela, o nome da coluna a ser filtrada e quantos dias de histórico manter. Outro script despeja determinadas tabelas em arquivos CSV e novamente é configurado com uma tabela listando as tabelas a serem despejadas. Essas tabelas de configuração podem usar o sysnametipo para armazenar nomes de tabelas e colunas.

Ed Avis
fonte
Você não precisa disso. Basta usar uma nvarchar(128) not nullcoluna. O nome é apenas isso, um nome. Não precisa sysnameser usado
Panagiotis Kanavos 03/06
Claro, e de fato nem precisa ser desse tipo, nvarchar(300)também funcionaria ou mesmo varcharse você não usar Unicode em nomes de tabelas (como tenho certeza que quase ninguém o faz). A vantagem de sysnameé parcialmente que torna a intenção mais clara: esta coluna contém um nome de objeto; e em parte, mesmo que você migre para uma versão diferente do MSSQL que altere o tipo de dados usado para nomes de objetos (como aconteceu antes), ele continuará sendo o tipo correto.
Ed Avis
Não, não. É apenas outro tipo de usuário (essencialmente um alias) mapeado nvarchar(128) NOT NULL. De fato, é assim que você pode encontrar o tipo - verificando o user_type_idvalor da coluna. Você não ganha nada mais usando esse tipo do que ganharia criando seu próprio tipo de usuário
Panagiotis Kanavos
Você quer dizer que se a definição de sysnamefosse alterada em uma versão mais recente do MSSQL e o backup do banco de dados fosse restaurado nessa instância mais recente, todas as colunas que foram anteriormente sysnameagora seriam do tipo errado e não corresponderiam mais ao tipo usado nas tabelas do sistema?
Ed Avis
Não pode, ou pior, se isso acontecer, sua coluna será mangueira. sysnameé um tipo definido pelo usuário com usert_type_id256. Não existe, ALTER TYPEportanto não há como alterá-lo. Você precisaria criar um novo tipo e alterar todas as colunas que usavam o tipo antigo para o novo. Se a MS decidisse mudar isso , teria que migrar os dados existentes da tabela do sistema para o novo tipo. Você pode esperar que eles façam isso nas tabelas de sistema que eles já conhecem, mas qualquer tabela de usuário teria que ser migrada pelos usuários
Panagiotis Kanavos