Qu'est-ce que le type de données SYSNAME dans SQL Server?

131

À quoi sert le type de données SQL Server SYSNAME? BOL dit:

Le type de données sysname est utilisé pour les colonnes de table, les variables et les paramètres de procédure stockée qui stockent les noms d'objet.

mais je ne comprends pas vraiment ça. Y a-t-il un cas d'utilisation que vous pouvez fournir?

jrara
la source
1
En plus de ces bonnes réponses ci-dessous, il est également utilisé pour causer des ravages pour quelqu'un essayant d'obtenir des métadonnées de colonne en utilisant sys.types, car il partage le même system_type_id que nvarchar.
StingyJack

Réponses:

150

sysnameest un type de données intégré limité à 128 caractères Unicode qui, IIRC, est principalement utilisé pour stocker les noms d'objets lors de la création de scripts. Sa valeur ne peut pas êtreNULL

C'est fondamentalement la même chose que d'utiliser nvarchar(128) NOT NULL

ÉDITER

Comme mentionné par @Jim dans les commentaires, je ne pense pas qu'il existe vraiment une analyse de rentabilisation que vous utiliseriez sysnamepour être honnête. Il est principalement utilisé par Microsoft lors de la création des systables internes et des procédures stockées, etc. dans SQL Server.

Par exemple, en exécutant, Exec sp_help 'sys.tables'vous verrez que la colonne nameest définie comme sysnamececi parce que la valeur de ceci est en fait un objet en soi (une table)

Je m'en inquiéterais trop.

Il convient également de noter que pour les personnes qui utilisent encore SQL Server 6.5 et versions antérieures (y a-t-il encore des personnes qui l'utilisent?), Le type intégré sysnamedevarchar(30)

Documentation

sysnameest défini avec la documentation pour ncharetnvarchar , dans la section remarques:

sysname est un type de données défini par l'utilisateur fourni par le système qui est fonctionnellement équivalent à nvarchar (128) , sauf qu'il n'est pas nullable. sysname est utilisé pour référencer les noms d'objets de base de données.

Pour clarifier les remarques ci-dessus, par défaut sysname est défini car NOT NULLil est certainement possible de le définir comme nullable. Il est également important de noter que la définition exacte peut varier entre les instances de SQL Server.

Utilisation de types de données spéciaux

Le type de données sysname est utilisé pour les colonnes de table, les variables et les paramètres de procédure stockée qui stockent les noms d'objet. La définition exacte de sysname est liée aux règles des identificateurs. Par conséquent, il peut varier entre les instances de SQL Server. sysname est fonctionnellement identique à nvarchar (128) sauf que, par défaut, sysname n'est PAS NULL. Dans les versions antérieures de SQL Server, sysname est défini comme varchar (30).

Vous trouverez de plus amples informations sur l' sysnameautorisation ou l'interdiction des NULLvaleurs ici https://stackoverflow.com/a/52290792/300863

Ce n'est pas parce que c'est la valeur par défaut (être NOT NULL) que cela ne garantit pas qu'il le sera!

codingbadger
la source
1
"Y a-t-il un cas d'utilisation que vous pouvez fournir?" Je ne pense pas que vous trouverez une raison commerciale pratique d'utiliser. La plupart du temps, il est utilisé en interne dans MS SQL car il est probablement un peu utilisé dans les tables, etc.
Jim
9
Vous utiliseriez sysnamepour la compatibilité ascendante (et descendante) dans vos scripts.
Martin Smith
il suffit de mettre 2 cents ici: les colonnes qui m'ont amené ici sont déclarées nvarchar(max)non nulles dans le SP mais elles s'affichent sous forme de a sysnamedans les tables sys.
gloomy.penguin
3
@Barry En fait ... d'après sys.typesc'est un nvarchar(256) not null. Notez que l'ID de type de système = 231 (nvarchar). Il fonctionne comme un alias de type dans TDS de nos jours; le premier ID d'un alias est 256, ce qui correspond à sysname. Quant à l'usage: sysnameest utilisé dans les schémas d'information.
atlaste
2
@atlaste La longueur max_length dans sys.tables est en octets. nvarchar utilise deux octets par caractère, c'est pourquoi il est défini comme nvarchar (128).
David Rushton
60

Y a-t-il un cas d'utilisation que vous pouvez fournir?

Si jamais vous avez besoin de créer un SQL dynamique, il convient de l'utiliser sysnamecomme type de données pour les variables contenant les noms de table, les noms de colonne et les noms de serveur.

Mikael Eriksson
la source
6

Tout comme un FYI ...

select * from sys.types where system_type_id = 231 vous donne deux lignes.

(Je ne sais pas encore ce que cela signifie, mais je suis sûr à 100% que cela gâche mon code en ce moment)

edit: je suppose que ce que cela signifie est que vous devez rejoindre par le user_type_id dans cette situation (ma situation) ou peut-être à la fois le user_type_id et l'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 

Cette requête:

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

donne:

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

et ça:

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

vous donne ceci:

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
sombre.pingouin
la source
sys.typescontient également les types définis par l' utilisateur que vous créez. Si vous le faites, create type MyInt from intvous aurez deux lignes avec system_type_id = 56. Un autre qui est dupliqué par défaut est 240, qui est le type de système pour hierarchyid, geometry et geography.
Mikael Eriksson
J'ai complètement oublié ça. Alors ... quelle est la manière idéale de rechercher ce truc avec le sysname là-dedans? puisque c'est un «alias», puis-je simplement faire where typ.name<>'sysname'ou est-ce que cela aurait une autre sorte de conséquence dont je ne suis pas conscient?
gloomy.penguin
3
Rejoignez sys.types à la fois sur system_type_id et user_type_id. SQL Fiddle
Mikael Eriksson
oh, c'est ce que j'ai dit tout en haut. Je pensais que vous disiez que c'était faux ...
gloomy.penguin
Désolé pour ça, pas ma signification. Je voulais juste souligner d'autres choses qui pourraient gâcher votre requête, non seulement sysname pourrait vous causer du chagrin sans rejoindre les deux colonnes.
Mikael Eriksson
3

Permettez-moi de lister un cas d'utilisation ci-dessous. J'espère que ça aide. Ici, j'essaie de trouver le propriétaire de la table 'Stud_dtls' de la base de données 'Students'. Comme Mikael l'a mentionné, sysname peut être utilisé lorsqu'il est nécessaire de créer un SQL dynamique qui nécessite des variables contenant des noms de table, des noms de colonnes et des noms de serveurs. Je viens de penser à fournir un exemple simple pour compléter son propos.

USE Students

DECLARE @TABLE_NAME sysname

SELECT @TABLE_NAME = 'Stud_dtls'

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

sysnameest utilisé par sp_send_dbmail, une procédure stockée qui «envoie un message électronique aux destinataires spécifiés» et située dans la base de données msdb.

Selon Microsoft ,

[ @profile_name = ] 'profile_name'  

Est le nom du profil à partir duquel envoyer le message. Le profile_name est de type sysname, avec la valeur par défaut NULL. Le nom_profil doit être le nom d'un profil de messagerie de base de données existant. Lorsqu'aucun nom_profil n'est spécifié, sp_send_dbmail utilise le profil privé par défaut pour l'utilisateur actuel. Si l'utilisateur n'a pas de profil privé par défaut, sp_send_dbmail utilise le profil public par défaut pour la base de données msdb. Si l'utilisateur n'a pas de profil privé par défaut et qu'il n'y a pas de profil public par défaut pour la base de données, @profile_name doit être spécifié.

utileBee
la source
1

FWIW, vous pouvez passer un nom de table aux SP système utiles comme celui-ci, si vous souhaitez explorer une base de données de cette façon:

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

Un autre cas d'utilisation est l'utilisation de la fonctionnalité SQL Server 2016+ de AT TIME ZONE

L'instruction ci-dessous renverra une date convertie en GMT

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

Si vous voulez passer le fuseau horaire en tant que variable, dites:

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

alors cette variable doit être du type sysname(la déclarer comme varcharprovoquant une erreur).

d219
la source
0

Y a-t-il un cas d'utilisation que vous pouvez fournir?

Partout où vous souhaitez stocker un nom d'objet à utiliser par les scripts de maintenance de base de données. Par exemple, un script purge les anciennes lignes de certaines tables qui ont une colonne de date. Il est configuré avec une table qui donne le nom de la table, le nom de la colonne sur laquelle filtrer et le nombre de jours d'historique à conserver. Un autre script vide certaines tables dans des fichiers CSV et est à nouveau configuré avec une table répertoriant les tables à vider. Ces tables de configuration peuvent utiliser le sysnametype pour stocker les noms de table et de colonne.

Ed Avis
la source
Vous n'en avez pas du tout besoin. Utilisez simplement une nvarchar(128) not nullcolonne. Le nom est juste ça, un nom. Il ne doit pas sysnameêtre utilisé
Panagiotis Kanavos
Bien sûr, et en fait cela n'a même pas besoin d'être de ce type, nvarchar(300)cela fonctionnerait aussi ou même varcharsi vous n'utilisez pas Unicode dans les noms de table (comme je suis sûr que presque personne ne le fait). L'avantage de sysnameest en partie qu'il rend l'intention plus claire: cette colonne contient un nom d'objet; et en partie que même si vous migrez vers une version différente de MSSQL qui change le type de données utilisé pour les noms d'objet (comme cela s'est produit auparavant), il continuera à être le bon type.
Ed Avis le
Non, ce n'est pas le cas. C'est juste un autre type d'utilisateur (essentiellement un alias) mappé nvarchar(128) NOT NULL. En fait, c'est ainsi que vous pouvez trouver le type - en vérifiant la user_type_idvaleur de la colonne. Vous ne gagnez rien de plus en utilisant ce type que vous ne le feriez en créant votre propre type d'utilisateur
Panagiotis Kanavos
Voulez-vous dire que si la définition de sysnameétait modifiée dans une version plus récente de MSSQL et que la base de données était sauvegardée et restaurée dans cette nouvelle instance, toutes les colonnes qui étaient auparavant sysnameseraient désormais du mauvais type et ne correspondraient plus au type utilisé dans les tables système?
Ed Avis le
Ça ne peut pas, ou pire, si cela arrive, votre colonne est arrosée. sysnameest un type défini par l'utilisateur avec usert_type_id256. Il n'y a pas ALTER TYPEdonc il n'y a aucun moyen de le changer. Vous devrez créer un nouveau type et remplacer toutes les colonnes qui utilisaient l'ancien type par le nouveau. Si MS décidait de changer cela, ils devraient migrer les données de table système existantes vers le nouveau type. Vous pouvez vous attendre à ce qu'ils le fassent pour les tables système qu'ils connaissent déjà, mais toutes les tables utilisateur devront être migrées par les utilisateurs
Panagiotis Kanavos