Che cos'è il tipo di dati SYSNAME in SQL Server?


131

A cosa serve il tipo di dati SYSNAME di SQL Server? BOL dice:

Il tipo di dati sysname viene utilizzato per colonne di tabella, variabili e parametri di stored procedure che memorizzano i nomi degli oggetti.

ma non lo capisco davvero. C'è un caso d'uso che puoi fornire?


1
Oltre a queste belle risposte di seguito, viene anche usato per causare scompiglio a qualcuno che cerca di ottenere metadati di colonna usando sys.types, perché condivide lo stesso system_type_id di nvarchar.
StingyJack,

Risposte:


150

sysnameè un tipo di dati incorporato limitato a 128 caratteri Unicode che, IIRC, viene utilizzato principalmente per memorizzare i nomi degli oggetti durante la creazione di script. Il suo valore non può essereNULL

È praticamente lo stesso che usare nvarchar(128) NOT NULL

MODIFICARE

Come menzionato da @Jim nei commenti, non penso che ci sia davvero un caso aziendale in cui useresti sysnameper essere onesto. Viene utilizzato principalmente da Microsoft durante la creazione di systabelle interne , stored procedure ecc. In SQL Server.

Ad esempio, eseguendo Exec sp_help 'sys.tables'vedrai che la colonna nameè definita come sysnamequesto perché il valore di questo è in realtà un oggetto in sé (una tabella)

Mi preoccuperei troppo.

Vale anche la pena notare che per quelle persone che usano ancora SQL Server 6.5 e versioni precedenti (ci sono ancora persone che lo usano?) Il tipo incorporato di sysnameè l'equivalente divarchar(30)

Documentazione

sysnameè definito con la documentazione per ncharenvarchar , nella sezione osservazioni:

sysname è un tipo di dati definito dall'utente fornito dal sistema che è funzionalmente equivalente a nvarchar (128) , tranne per il fatto che non è nullable. sysname viene utilizzato per fare riferimento ai nomi degli oggetti del database.

Per chiarire le osservazioni di cui sopra, per impostazione predefinita viene definito sysname in NOT NULLquanto è certamente possibile definirlo come nullable. È anche importante notare che la definizione esatta può variare tra istanze di SQL Server.

Utilizzo di tipi di dati speciali

Il tipo di dati sysname viene utilizzato per colonne di tabella, variabili e parametri di stored procedure che memorizzano i nomi degli oggetti. La definizione esatta di sysname è correlata alle regole per gli identificatori. Pertanto, può variare tra istanze di SQL Server. sysname è funzionalmente uguale a nvarchar (128) tranne per il fatto che, per impostazione predefinita, sysname non è NULL. Nelle versioni precedenti di SQL Server, sysname è definito come varchar (30).

Alcune ulteriori informazioni su come sysnameconsentire o non consentire i NULLvalori sono disponibili qui https://stackoverflow.com/a/52290792/300863

Solo perché è l'impostazione predefinita (per essere NON NULL) non garantisce che lo sarà!


1
"C'è un caso d'uso che puoi fornire?" Non credo che troverai un motivo commerciale pratico per l'utilizzo. Principalmente viene utilizzato internamente in MS SQL in quanto è probabilmente usato abbastanza nelle tabelle, ecc.
Jim

9
Utilizzeresti sysnameper la compatibilità in avanti (e indietro) nei tuoi script.
Martin Smith,

inserendo solo 2 centesimi qui: le colonne che mi hanno portato qui sono dichiarate come nvarchar(max)non nulle nella SP ma sono mostrate come sysnamenelle tabelle sys.
gloomy.penguin,

3
@Barry In realtà ... secondo sys.typesè a nvarchar(256) not null. Si noti che ID tipo di sistema = 231 (nvarchar). Al giorno d'oggi funziona come un alias di tipo in TDS; il primo ID di un alias è 256, che corrisponde a sysname. Per quanto riguarda l'utilizzo: sysnameviene utilizzato negli schemi di informazioni.
Atlanta

2
@atlaste La lunghezza max_length in sys.tables è in byte. nvarchar utilizza due byte per carattere, motivo per cui è definito come nvarchar (128).
David Rushton,

60

C'è un caso d'uso che puoi fornire?

Se mai hai la necessità di creare un sql dinamico , è opportuno utilizzare sysnamecome tipo di dati per variabili che contengono nomi di tabelle, nomi di colonne e nomi di server.


6

Proprio come un FYI ....

select * from sys.types where system_type_id = 231 ti dà due file.

(Non sono sicuro di cosa significhi ancora, ma sono sicuro al 100% che adesso sta rovinando il mio codice)

modifica: suppongo che ciò significhi che dovresti unirti a user_type_id in questa situazione (la mia situazione) o possibilmente sia user_type_id che 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 

Questa query:

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

rendimenti:

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 questo:

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

ti dà questo:

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.typescontiene anche i tipi definiti dall'utente che crei. Se lo fai create type MyInt from intavrai due file con system_type_id = 56. Un altro che è duplicato per impostazione predefinita è 240, che è il tipo di sistema per hierarchyid, geometria e geografia.
Mikael Eriksson,

Me ne sono completamente dimenticato. Quindi ... qual è il modo ideale per cercare questa roba con il sysname lì dentro? dal momento che è un 'alias' posso semplicemente fare where typ.name<>'sysname'o avrebbe qualche altra conseguenza di cui non sono a conoscenza?
gloomy.penguin,

3
Partecipa contro sys.types su system_type_id e user_type_id. SQL Fiddle
Mikael Eriksson

oh, è quello che ho detto in cima. Pensavo stessi dicendo che era sbagliato ...
gloomy.penguin,

Mi dispiace per quello, non per il mio significato. Volevo solo sottolineare alcune altre cose che potrebbero confondere la tua query, non solo sysname potrebbe causare dolore senza unirti ad entrambe le colonne.
Mikael Eriksson,

3

Vorrei elencare un caso d'uso di seguito. Spero che sia d'aiuto. Qui sto cercando di trovare il proprietario della tabella "Stud_dtls" dal DB "Studenti". Come menzionato da Mikael, sysname potrebbe essere usato quando è necessario creare un sql dinamico che necessita di variabili che contengono nomi di tabella, nomi di colonne e nomi di server. Ho solo pensato di fornire un semplice esempio per integrare il suo punto.

USE Students

DECLARE @TABLE_NAME sysname

SELECT @TABLE_NAME = 'Stud_dtls'

SELECT TABLE_SCHEMA 
  FROM INFORMATION_SCHEMA.Tables
 WHERE TABLE_NAME = @TABLE_NAME

2

sysnameviene utilizzata da sp_send_dbmailuna procedura memorizzata che "Invia un messaggio di posta elettronica ai destinatari specificati" e si trova nel database msdb.

Secondo Microsoft ,

[ @profile_name = ] 'profile_name'  

Nome del profilo da cui inviare il messaggio. Profile_name è di tipo sysname, con un valore predefinito NULL. Nome_profilo deve essere il nome di un profilo di posta elettronica database esistente. Quando non viene specificato nessun nome_profilo, sp_send_dbmail utilizza il profilo privato predefinito per l'utente corrente. Se l'utente non ha un profilo privato predefinito, sp_send_dbmail utilizza il profilo pubblico predefinito per il database msdb. Se l'utente non ha un profilo privato predefinito e non esiste un profilo pubblico predefinito per il database, è necessario specificare @profile_name.


1

FWIW, puoi passare un nome di tabella a SP di sistema utili come questo, se desideri esplorare un database in questo modo:

DECLARE @Table sysname; SET @Table = 'TableName';
EXEC sp_fkeys @Table;
EXEC sp_help @Table;

0

Un altro caso d'uso è quando si utilizza la funzionalità di SQL Server 2016+ di AT TIME ZONE

La seguente dichiarazione restituirà una data convertita in GMT

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

Se si desidera passare il fuso orario come variabile, dire:

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

quindi quella variabile deve essere del tipo sysname(dichiarandola come varcharcauserà un errore).


0

C'è un caso d'uso che puoi fornire?

Ovunque si desideri memorizzare un nome oggetto da utilizzare con gli script di manutenzione del database. Ad esempio, uno script elimina le vecchie righe da alcune tabelle con una colonna data. È configurato con una tabella che fornisce il nome della tabella, il nome della colonna su cui filtrare e il numero di giorni della cronologia da conservare. Un altro script scarica alcune tabelle in file CSV e viene nuovamente configurato con una tabella che elenca le tabelle da scaricare. Queste tabelle di configurazione possono utilizzare il sysnametipo per memorizzare i nomi di tabelle e colonne.


Non ti serve affatto. Usa solo una nvarchar(128) not nullcolonna. Il nome è proprio questo, un nome. Non deve sysnameessere usato
Panagiotis Kanavos

Certo, e in effetti non deve nemmeno essere di quel tipo, nvarchar(300)funzionerebbe troppo o anche solo varcharse non usi Unicode nei nomi delle tabelle (come sono sicuro che quasi nessuno lo fa). Il vantaggio di sysnameè in parte quello di rendere più chiara l'intenzione: questa colonna contiene un nome di oggetto; e in parte anche se si passa a una versione diversa di MSSQL che modifica il tipo di dati utilizzato per i nomi degli oggetti (come è successo prima), continuerà ad essere il tipo giusto.
Ed Avis,

No non lo fa. È solo un altro tipo di utente (essenzialmente un alias) mappato nvarchar(128) NOT NULL. In effetti, è così che puoi trovare il tipo, controllando il user_type_idvalore della colonna. Usando quel tipo non guadagni nulla di più di quanto creeresti il ​​tuo tipo di utente
Panagiotis Kanavos

Vuoi dire che se la definizione di sysnamefosse cambiata in una versione MSSQL più recente e il backup del database fosse ripristinato in quella nuova istanza, tutte le colonne che erano state in precedenza sysnameora sarebbero del tipo sbagliato e non corrisponderebbero più al tipo usato nelle tabelle di sistema?
Ed Avis,

Non può, o peggio, se ciò dovesse mai accadere, la tua colonna è chiusa. sysnameè un tipo definito dall'utente con usert_type_id256. Non c'è ALTER TYPEquindi non c'è modo di cambiarlo. Dovresti creare un nuovo tipo e cambiare tutte le colonne che hanno usato il vecchio tipo con quello nuovo. Se gli Stati membri decidessero di modificarlo , dovrebbero migrare i dati delle tabelle di sistema esistenti nel nuovo tipo. Puoi aspettarti che lo facciano per le tabelle di sistema che già conoscono, ma qualsiasi tabella utente dovrebbe essere migrata dagli utenti
Panagiotis Kanavos
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.