Was ist der Datentyp SYSNAME in SQL Server?

131

Wofür ist der SQL Server SYSNAME-Datentyp? BOL sagt:

Der Datentyp sysname wird für Tabellenspalten, Variablen und Parameter für gespeicherte Prozeduren verwendet, in denen Objektnamen gespeichert werden.

aber das verstehe ich nicht wirklich. Gibt es einen Anwendungsfall, den Sie bereitstellen können?

jrara
quelle
1
Zusätzlich zu diesen feinen Antworten unten wird es auch verwendet, um jemanden zu verwüsten, der versucht, Spaltenmetadaten mit sys.types abzurufen, da es dieselbe system_type_id wie nvarchar verwendet.
StingyJack

Antworten:

150

sysnameist ein integrierter Datentyp, der auf 128 Unicode-Zeichen beschränkt ist und in IIRC hauptsächlich zum Speichern von Objektnamen beim Erstellen von Skripten verwendet wird. Sein Wert kann nicht seinNULL

Es ist im Grunde das gleiche wie mit nvarchar(128) NOT NULL

BEARBEITEN

Wie von @Jim in den Kommentaren erwähnt, glaube ich nicht, dass es wirklich einen Business Case gibt, in dem Sie sysnameehrlich sein würden. Es wird hauptsächlich von Microsoft beim Erstellen der internen sysTabellen und gespeicherten Prozeduren usw. in SQL Server verwendet.

Wenn Sie beispielsweise ausführen, sehen Exec sp_help 'sys.tables'Sie, dass die Spalte nameso definiert sysnameist, weil der Wert davon tatsächlich ein Objekt an sich ist (eine Tabelle).

Ich würde mir zu viele Sorgen machen.

Es ist auch erwähnenswert, dass für diejenigen, die noch SQL Server 6.5 und niedriger verwenden (gibt es noch Leute, die es verwenden?), Der eingebaute Typ von sysnamegleichbedeutend ist mitvarchar(30)

Dokumentation

sysnamewird mit der Dokumentation für ncharundnvarchar im Abschnitt "Bemerkungen" definiert:

sysname ist ein vom System bereitgestellter benutzerdefinierter Datentyp, der funktional nvarchar (128) entspricht , außer dass er nicht nullwertfähig ist. sysname wird verwendet, um auf Datenbankobjektnamen zu verweisen.

Um die obigen Ausführungen zu verdeutlichen, wird standardmäßig sysname definiert, da NOT NULLes durchaus möglich ist, ihn als nullbar zu definieren. Es ist auch wichtig zu beachten, dass die genaue Definition zwischen Instanzen von SQL Server variieren kann.

Spezielle Datentypen verwenden

Der Datentyp sysname wird für Tabellenspalten, Variablen und Parameter für gespeicherte Prozeduren verwendet, in denen Objektnamen gespeichert werden. Die genaue Definition von sysname hängt mit den Regeln für Bezeichner zusammen. Daher kann es zwischen Instanzen von SQL Server variieren. sysname ist funktional identisch mit nvarchar (128), außer dass sysname standardmäßig NICHT NULL ist. In früheren Versionen von SQL Server ist sysname als varchar (30) definiert.

Weitere Informationen zum sysnameZulassen oder Nichtzulassen von NULLWerten finden Sie hier https://stackoverflow.com/a/52290792/300863

Nur weil es die Standardeinstellung ist (NICHT NULL zu sein), kann dies nicht garantiert werden!

Codierungsbadger
quelle
1
"Gibt es einen Anwendungsfall, den Sie bereitstellen können?" Ich glaube nicht, dass Sie einen praktischen Geschäftsgrund für die Verwendung finden werden. Meistens wird es intern in MS SQL verwendet, da es wahrscheinlich ziemlich
Jim
9
Sie würden sysnamefür die Vorwärts- (und Rückwärts-) Kompatibilität in Ihren Skripten verwenden.
Martin Smith
Geben Sie hier nur 2 Cent ein: Die Spalten, die mich hierher gebracht haben, werden nvarchar(max)im SP als nicht null deklariert, aber sysnamein den sys-Tabellen als a angezeigt.
gloomy.penguin
3
@Barry Eigentlich ... laut sys.typeses ist ein nvarchar(256) not null. Beachten Sie, dass der Systemtyp ID = 231 (nvarchar) ist. Es funktioniert heutzutage als Typalias in TDS. Die erste ID eines Alias ​​ist 256, was entspricht sysname. Verwendung: sysnameWird in Informationsschemata verwendet.
Atlaste
2
@atlaste Die maximale Länge in sys.tables wird in Byte angegeben. nvarchar verwendet zwei Bytes pro Zeichen, weshalb es als nvarchar (128) definiert ist.
David Rushton
60

Gibt es einen Anwendungsfall, den Sie bereitstellen können?

Wenn Sie jemals die Notwendigkeit haben, einige zu erstellen dynamische SQL sollten Sie diese sysnameals Datentyp für Variablen verwenden, die Tabellennamen, Spaltennamen und Servernamen enthalten.

Mikael Eriksson
quelle
6

Nur als FYI ....

select * from sys.types where system_type_id = 231 gibt Ihnen zwei Zeilen.

(Ich bin mir noch nicht sicher, was das bedeutet, aber ich bin mir zu 100% sicher, dass es meinen Code gerade durcheinander bringt.)

edit: ich denke was es bedeutet ist, dass du in dieser Situation (meiner Situation) durch die user_type_id oder möglicherweise sowohl die user_type_id als auch die essystem_type_id beitreten solltest

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 

Diese Abfrage:

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

Ausbeuten:

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

und das:

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

gibt Ihnen dies:

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
düster.penguin
quelle
sys.typesEnthält die benutzerdefinierten Typen , die Sie ebenfalls erstellen. Wenn Sie dies tun create type MyInt from int, haben Sie zwei Zeilen mit system_type_id = 56. Eine andere, die standardmäßig dupliziert wird, ist 240, der Systemtyp für Hierarchie-ID, Geometrie und Geografie.
Mikael Eriksson
Das habe ich völlig vergessen. Also ... was ist der ideale Weg, um dieses Zeug mit dem Systemnamen dort abzufragen? Da es sich um einen Alias ​​handelt, kann ich das einfach tun where typ.name<>'sysname'oder hätte das eine andere Konsequenz, von der ich nichts weiß?
gloomy.penguin
3
Join gegen sys.types sowohl auf system_type_id als auch auf user_type_id. SQL Fiddle
Mikael Eriksson
Oh, das habe ich ganz oben gesagt. Ich dachte, Sie sagten, das sei falsch ...
düster.penguin
Tut mir leid, nicht meine Bedeutung. Ich wollte nur auf einige andere Dinge hinweisen, die Ihre Abfrage durcheinander bringen könnten. Nicht nur der Systemname könnte Ihnen Kummer bereiten, ohne sich beiden Spalten anzuschließen.
Mikael Eriksson
3

Lassen Sie mich unten einen Anwendungsfall auflisten. Ich hoffe es hilft. Hier versuche ich, den Tabellenbesitzer der Tabelle 'Stud_dtls' aus den DB 'Students' zu finden. Wie Mikael erwähnte, könnte sysname verwendet werden, wenn eine dynamische SQL erstellt werden muss, für die Variablen mit Tabellennamen, Spaltennamen und Servernamen erforderlich sind. Ich dachte nur daran, ein einfaches Beispiel zu liefern, um seinen Standpunkt zu ergänzen.

USE Students

DECLARE @TABLE_NAME sysname

SELECT @TABLE_NAME = 'Stud_dtls'

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

sysname wird verwendet von sp_send_dbmail einer gespeicherten Prozedur verwendet, die "eine E-Mail-Nachricht an die angegebenen Empfänger sendet" und sich in der msdb-Datenbank befindet.

Laut Microsoft ,

[ @profile_name = ] 'profile_name'  

Ist der Name des Profils, von dem die Nachricht gesendet werden soll. Der Profilname ist vom Typ sysname mit dem Standardwert NULL. Der Profilname muss der Name eines vorhandenen Datenbank-Mail-Profils sein. Wenn kein Profilname angegeben wird, verwendet sp_send_dbmail das private Standardprofil für den aktuellen Benutzer. Wenn der Benutzer kein privates Standardprofil hat, verwendet sp_send_dbmail das öffentliche Standardprofil für die msdb-Datenbank. Wenn der Benutzer kein privates Standardprofil hat und kein öffentliches Standardprofil für die Datenbank vorhanden ist, muss @profile_name angegeben werden.

nützlichBee
quelle
1

FWIW, Sie können einen Tabellennamen an nützliche System-SPs wie diese übergeben, wenn Sie eine Datenbank auf diese Weise durchsuchen möchten:

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

Ein weiterer Anwendungsfall ist die Verwendung der SQL Server 2016+ -Funktionalität von AT TIME ZONE

Die folgende Anweisung gibt ein in GMT konvertiertes Datum zurück

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

Wenn Sie die Zeitzone als Variable übergeben möchten, sagen Sie:

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

dann muss diese Variable vom Typ sein sysname(wenn sie als varcharfehlerhaft deklariert wird).

d219
quelle
0

Gibt es einen Anwendungsfall, den Sie bereitstellen können?

Überall dort, wo Sie einen Objektnamen zur Verwendung durch Datenbankwartungsskripte speichern möchten. Ein Skript löscht beispielsweise alte Zeilen aus bestimmten Tabellen mit einer Datumsspalte. Es ist mit einer Tabelle konfiguriert, die den Tabellennamen, den Spaltennamen zum Filtern und die Anzahl der Tage des Verlaufs angibt. Ein anderes Skript speichert bestimmte Tabellen in CSV-Dateien und wird erneut mit einer Tabelle konfiguriert, in der die zu sichernden Tabellen aufgelistet sind. Diese Konfigurationstabellen können den sysnameTyp zum Speichern von Tabellen- und Spaltennamen verwenden.

Ed Avis
quelle
Das brauchst du überhaupt nicht. Verwenden Sie einfach eine nvarchar(128) not nullSpalte. Der Name ist genau das, ein Name. Es muss nicht sysnameverwendet werden
Panagiotis Kanavos
Sicher, und tatsächlich muss es nicht einmal von diesem Typ sein, nvarchar(300)würde auch funktionieren oder auch nur, varcharwenn Sie Unicode nicht in Tabellennamen verwenden (wie ich sicher bin, dass fast niemand dies tut). Der Vorteil von sysnameist teilweise, dass es die Absicht klarer macht: Diese Spalte enthält einen Objektnamen; und teilweise, dass selbst wenn Sie auf eine andere Version von MSSQL migrieren, die den für Objektnamen verwendeten Datentyp ändert (wie zuvor), dieser weiterhin der richtige Typ ist.
Ed Avis
Nein, tut es nicht. Es ist nur ein anderer Benutzertyp (im Wesentlichen ein Alias), der zugeordnet ist nvarchar(128) NOT NULL. Auf diese Weise können Sie den Typ finden - indem Sie den user_type_idWert der Spalte überprüfen . Mit diesem Typ erhalten Sie nichts mehr als mit dem Erstellen eines eigenen Benutzertyps
Panagiotis Kanavos
Meinen Sie das, wenn die Definition von sysname in einer neueren MSSQL-Version geändert und die Datenbank gesichert und in dieser neueren Instanz wiederhergestellt würde, alle zuvor vorhandenen Spalten sysnamejetzt vom falschen Typ wären und nicht mehr mit dem verwendeten Typ übereinstimmen würden in den Systemtabellen?
Ed Avis
Es kann nicht oder schlimmer noch, wenn das jemals passiert, ist Ihre Säule abgespritzt. sysnameist ein benutzerdefinierter Typ mit usert_type_id256. Es gibt keinen, ALTER TYPEalso gibt es keine Möglichkeit, ihn zu ändern. Sie müssten einen neuen Typ erstellen und alle Spalten, die den alten Typ verwendet haben, in den neuen ändern. Wenn MS jemals beschlossen , dies ändern würden sie müssen bestehende Systemtabellendaten in den neuen Typ migrieren. Sie können erwarten, dass sie dies für die Systemtabellen tun, die sie bereits kennen, aber für jeden Benutzer
Systemtabellen