¿Qué es el tipo de datos SYSNAME en SQL Server?

131

¿Para qué es el tipo de datos SYSNAME de SQL Server? BOL dice:

El tipo de datos sysname se usa para columnas de tabla, variables y parámetros de procedimientos almacenados que almacenan nombres de objetos.

pero realmente no entiendo eso. ¿Hay un caso de uso que pueda proporcionar?

jrara
fuente
1
Además de estas excelentes respuestas a continuación, también se usa para causar estragos a alguien que intenta obtener metadatos de columna usando sys.types, porque comparte el mismo system_type_id que nvarchar.
StingyJack

Respuestas:

150

sysnamees un tipo de datos integrado limitado a 128 caracteres Unicode que, IIRC, se usa principalmente para almacenar nombres de objetos al crear scripts. Su valor no puede serNULL

Básicamente es lo mismo que usar nvarchar(128) NOT NULL

EDITAR

Como mencionó @Jim en los comentarios, no creo que haya realmente un caso de negocios en el que sysnamepueda ser sincero. Microsoft lo utiliza principalmente al crear systablas internas y procedimientos almacenados, etc. en SQL Server.

Por ejemplo, al ejecutar Exec sp_help 'sys.tables', verá que la columna namese define como sysnameesto porque el valor de esto es en realidad un objeto en sí mismo (una tabla)

Me preocuparía demasiado por eso.

También vale la pena señalar que para aquellas personas que todavía usan SQL Server 6.5 y versiones anteriores (¿todavía hay personas que lo usan?), El tipo incorporado sysnamees el equivalente devarchar(30)

Documentación

sysnamese define con la documentación para ncharynvarchar , en la sección de comentarios:

sysname es un tipo de datos definido por el usuario proporcionado por el sistema que es funcionalmente equivalente a nvarchar (128) , excepto que no es anulable. sysname se usa para hacer referencia a nombres de objetos de bases de datos.

Para aclarar los comentarios anteriores, por defecto se define sysname ya NOT NULLque ciertamente es posible definirlo como anulable. También es importante tener en cuenta que la definición exacta puede variar entre instancias de SQL Server.

Usar tipos de datos especiales

El tipo de datos sysname se usa para columnas de tabla, variables y parámetros de procedimientos almacenados que almacenan nombres de objetos. La definición exacta de sysname está relacionada con las reglas para los identificadores. Por lo tanto, puede variar entre instancias de SQL Server. sysname es funcionalmente igual que nvarchar (128), excepto que, de forma predeterminada, sysname NO es NULL. En versiones anteriores de SQL Server, sysname se define como varchar (30).

Puede encontrar más información sobre sysnamepermitir o rechazar NULLvalores aquí https://stackoverflow.com/a/52290792/300863

El hecho de que sea el valor predeterminado (para que NO sea NULL) no garantiza que lo sea.

codingbadger
fuente
1
"¿Hay algún caso de uso que pueda proporcionar?" No creo que encuentre una razón comercial práctica para usar. Principalmente se usa internamente en MS SQL, ya que probablemente se usa bastante en tablas, etc.
Jim
9
Lo usarías sysnamepara la compatibilidad hacia adelante (y hacia atrás) en tus scripts.
Martin Smith
solo pongo 2 centavos aquí: las columnas que me trajeron aquí se declaran nvarchar(max)no nulas en el SP pero se muestran como a sysnameen las tablas del sistema.
gloomy.penguin
3
@Barry En realidad ... según sys.typeses a nvarchar(256) not null. Tenga en cuenta que el tipo de sistema ID = 231 (nvarchar). Funciona como un alias de tipo en TDS hoy en día; la primera ID de un alias es 256, que corresponde a sysname. En cuanto al uso: sysnamese utiliza en esquemas de información.
atlaste
2
@atlaste La longitud máxima_length en sys.tables está en bytes. nvarchar usa dos bytes por carácter, por eso se define como nvarchar (128).
David Rushton el
60

¿Hay algún caso de uso que pueda proporcionar?

Si alguna vez tiene la necesidad de crear algún sql dinámico , es apropiado usarlo sysnamecomo tipo de datos para variables que contienen nombres de tablas, columnas y servidores.

Mikael Eriksson
fuente
6

Solo como un FYI ...

select * from sys.types where system_type_id = 231 te da dos filas

(No estoy seguro de lo que esto significa todavía, pero estoy 100% seguro de que está desordenando mi código en este momento)

editar: supongo que lo que significa es que debes unirte por user_type_id en esta situación (mi situación) o posiblemente tanto user_type_id como th esystem_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

rendimientos:

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

y esto:

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

te da esto:

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
fuente
sys.typescontiene los tipos definidos por el usuario que usted crea también. Si lo haces create type MyInt from int, tendrás dos filas con system_type_id = 56. Otro que está duplicado por defecto es 240, que es el tipo de sistema para jerarquía, geometría y geografía.
Mikael Eriksson
Me olvidé por completo de eso. Entonces ... ¿cuál es la forma ideal de consultar estas cosas con el nombre del sistema allí? ya que es un 'alias', ¿puedo hacer where typ.name<>'sysname'o tendría algún otro tipo de consecuencia que desconozco?
gloomy.penguin
3
Únase contra sys.types en system_type_id y user_type_id. SQL Fiddle
Mikael Eriksson
oh, eso es lo que dije en la parte superior. Pensé que estabas diciendo que eso estaba mal ...
gloomy.penguin
Lo siento, no es mi significado. Solo quería señalar otras cosas que podrían estropear su consulta, no solo sysname podría causarle dolor sin unirse en ambas columnas.
Mikael Eriksson
3

Permítanme enumerar un caso de uso a continuación. Espero eso ayude. Aquí estoy tratando de encontrar el propietario de la tabla 'Stud_dtls' de la base de datos 'Estudiantes'. Como mencionó Mikael, sysname podría usarse cuando sea necesario crear algunos sql dinámicos que necesiten variables que contengan nombres de tablas, columnas y servidores. Solo pensé en proporcionar un ejemplo simple para complementar su punto.

USE Students

DECLARE @TABLE_NAME sysname

SELECT @TABLE_NAME = 'Stud_dtls'

SELECT TABLE_SCHEMA 
  FROM INFORMATION_SCHEMA.Tables
 WHERE TABLE_NAME = @TABLE_NAME
aok
fuente
2

sysnamees utilizado por sp_send_dbmailun procedimiento almacenado que "envía un mensaje de correo electrónico a los destinatarios especificados" y ubicado en la base de datos msdb.

De acuerdo con Microsoft ,

[ @profile_name = ] 'profile_name'  

Es el nombre del perfil desde el que se envía el mensaje. Profile_name es de tipo sysname, con un valor predeterminado de NULL. Profile_name debe ser el nombre de un perfil de Correo electrónico de base de datos existente. Cuando no se especifica profile_name, sp_send_dbmail usa el perfil privado predeterminado para el usuario actual. Si el usuario no tiene un perfil privado predeterminado, sp_send_dbmail usa el perfil público predeterminado para la base de datos msdb. Si el usuario no tiene un perfil privado predeterminado y no hay un perfil público predeterminado para la base de datos, se debe especificar @profile_name.

útilBee
fuente
1

FWIW, puede pasar un nombre de tabla a SP del sistema útiles como este, si desea explorar una base de datos de esa manera:

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

Otro caso de uso es cuando se usa la funcionalidad SQL Server 2016+ de AT TIME ZONE

La siguiente declaración devolverá una fecha convertida a GMT

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

Si desea pasar la zona horaria como una variable, diga:

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

entonces esa variable debe ser del tipo sysname(declararla como varcharcausará un error).

d219
fuente
0

¿Hay algún caso de uso que pueda proporcionar?

En cualquier lugar donde desee almacenar un nombre de objeto para que lo utilicen los scripts de mantenimiento de la base de datos. Por ejemplo, un script purga las filas antiguas de ciertas tablas que tienen una columna de fecha. Está configurado con una tabla que proporciona el nombre de la tabla, el nombre de la columna para filtrar y cuántos días de historial guardar. Otro script volca ciertas tablas en archivos CSV, y nuevamente se configura con una tabla que enumera las tablas para volcar. Estas tablas de configuración pueden usar el sysnametipo para almacenar nombres de tablas y columnas.

Ed Avis
fuente
No necesitas eso en absoluto. Solo usa una nvarchar(128) not nullcolumna. El nombre es solo eso, un nombre. No tiene que ser sysnameusado
Panagiotis Kanavos
Claro, y de hecho ni siquiera tiene que ser de ese tipo, nvarchar(300)también funcionaría o incluso varcharsi no usa Unicode en los nombres de las tablas (como estoy seguro de que casi nadie lo hace). La ventaja de sysnamees en parte que aclara la intención: esta columna contiene un nombre de objeto; y, en parte, que incluso si migra a una versión diferente de MSSQL que cambia el tipo de datos utilizado para los nombres de objetos (como ha sucedido antes), seguirá siendo el tipo correcto.
Ed Avis
No, no lo hace. Es solo otro tipo de usuario (esencialmente un alias) asignado nvarchar(128) NOT NULL. De hecho, así es como puede encontrar el tipo, verificando el user_type_idvalor de la columna. Al ganar ese tipo, no gana nada más de lo que ganaría al crear su propio tipo de usuario
Panagiotis Kanavos
¿Quiere decir que si la definición de sysnamese cambiara en una versión más reciente de MSSQL, y la base de datos fuera respaldada y restaurada en esa instancia más nueva, todas las columnas que habían sido anteriormente sysnameahora serían del tipo incorrecto y ya no coincidirían con el tipo usado en las tablas del sistema?
Ed Avis
No puede, o peor, si eso sucede, su columna está manguera. sysnamees un tipo definido por el usuario con usert_type_id256. No hay, ALTER TYPEasí que no hay forma de cambiarlo. Tendría que crear un nuevo tipo y cambiar todas las columnas que usaban el tipo antiguo por el nuevo. Si MS alguna vez decidiera cambiar esto , tendrían que migrar los datos de la tabla del sistema existente al nuevo tipo. Puede esperar que hagan esto para las tablas del sistema que ya conocen, pero cualquier tabla de usuario tendría que ser migrada por los usuarios
Panagiotis Kanavos