Wie benenne ich die eindeutige Einschränkung der Tabellenvariablenfunktion?


7

Ich benenne einige eindeutige Einschränkungen um, um sie unserer Namenskonvention für Datenbankobjekte anzupassen. Seltsamerweise gibt es mehrere mehrzeilige Tabellenwertfunktionen, für die die zurückgegebene Tabelle eindeutige Einschränkungen aufweist:

CREATE FUNCTION [dbo].[fn_name] (...)
RETURNS @Result 
TABLE
(
    ID BIGINT PRIMARY KEY,
    ...
    RowNum BIGINT UNIQUE 
)
BEGIN
    ...
    RETURN
END
GO

Ich habe versucht, es so zu benennen, aber es funktioniert nicht:

CREATE FUNCTION [dbo].[fn_name] (...)
RETURNS @Result 
TABLE
(
    ID BIGINT PRIMARY KEY,
    ...
    RowNum BIGINT
    ,CONSTRAINT UC_fn_name_RowNum UNIQUE([RowNum])  
)
BEGIN
    ...
    RETURN
END
GO

Ist es möglich, den Namen einer eindeutigen Einschränkung festzulegen, wenn diese Teil der Funktionsdefinition für Tabellenvariablen ist?

Antworten:


8

Tabellenvariablen, unabhängig davon, ob sie aus einer DECLAREoder einer RETURNSin einer CREATE FUNCTIONAnweisung erstellt wurden, sowie benutzerdefinierte Tabellentypen (UDTTs) ermöglichen keine Benennung von Einschränkungen. Laut der MSDN-Seite für CREATE FUNCTION :

Argumente
...
        <Spaltenbeschränkung> :: = und <Tabellenbeschränkung> :: =
        ... Benannte Einschränkungen sind nicht zulässig.

Eine "angegebene" Ausnahme von dieser Regel befindet sich auf der MSDN-Seite für DECLARE @local_variable, die besagt (unter der Erläuterung von DEFAULT ):

Um die Kompatibilität mit früheren Versionen von SQL Server zu gewährleisten, kann einem DEFAULT ein Einschränkungsname zugewiesen werden.

Es scheint jedoch, dass dies ein Fehler in der Dokumentation ist, da ich einer DEFAULT-Einschränkung keinen Namen zuweisen kann. Es gibt keine Beschreibung der Syntax, um dies zu erreichen, und es gibt keine Beispiele dafür in der Dokumentation (ich habe nachgesehen bereits SQL Server 2000).

Wenn es um temporäre Tabellen geht, ist das Problem etwas einfacher: Wenn Sie explizit Einschränkungen benennen, kann der Code nicht in zwei verschiedenen Sitzungen gleichzeitig ausgeführt werden. Einschränkungen sind Objekte (im Gegensatz zu Indizes) und müssen eindeutige Namen innerhalb desselben Schemas haben. Wenn also ein Code eine lokale temporäre Tabelle mit Einschränkungen erstellt, denen Namen zugewiesen wurden, wird in der zweiten Sitzung aufgrund des Namenskonflikts ein Fehler angezeigt, wenn zwei Sitzungen diesen Code gleichzeitig ausführen (Dies tritt auf tempdb, wenn temporäre Tabellen vorhanden sind). Führen Sie beispielsweise in einer Abfrageregisterkarte in SSMS Folgendes aus:

CREATE TABLE #Session1 (Col1 INT NOT NULL CONSTRAINT [UQ_DifferentSession] UNIQUE);

Führen Sie auf einer anderen Registerkarte für Abfragen Folgendes aus:

CREATE TABLE #Session2 (Col1 INT NOT NULL CONSTRAINT [UQ_DifferentSession] UNIQUE);

Selbst wenn die temporären Tabellen nicht nur lokale temporäre Tabellen sind, die in verschiedenen Sitzungen erstellt wurden, sondern auch unterschiedliche Namen haben, wird der folgende Fehler angezeigt:

Nachricht 2714, Ebene 16,
Status 5, Zeile 1 In der Datenbank befindet sich bereits ein Objekt mit dem Namen 'UQ_DifferentSession'.
Meldung 1750, Ebene 16, Status 0, Zeile 1 Es
konnte keine Einschränkung erstellt werden. Siehe vorherige Fehler.

Ähnlich wie bei temporären Tabellen haben auch Tabellenvariablen keine Definition, bis sie "deklariert" werden und sich diese Definition dann nur in befindet tempdb. Wir können jedoch keine Namenskollisionen für Tabellenvariablen testen, da Sie deren Einschränkungen nicht benennen können.

Zurückgegebene Tabellen in TVFs mit mehreren Anweisungen und benutzerdefinierte Tabellentypen existieren dagegen etwas anders als temporäre Tabellen, da sie ihre Definition in der Datenbank speichern, in der sie existieren. Die Metadaten, die sie in ihrer lokalen Datenbank speichern, werden jedoch niemals zum Speichern von Daten verwendet. Ihre Metadaten werden nur als Vorlage für das verwendet, was (bei Bedarf) in erstellt wird tempdb. Wenn diese Metadaten- "Vorlage" verwendet wird, erhalten die benannten Objekte in tempdb(Primärschlüssel, eindeutige Einschränkungen, Standardbeschränkungen und Prüfbeschränkungen) dynamisch generierte Namen in Form von UQ__#BC4FB52__A259EE56FAB8BB6F.


In Bezug auf den Wunsch, die Einschränkungen zu benennen, um den Namenskonventionen zu entsprechen (wie in einem Kommentar zur Frage angegeben):

Es würde zwar nichts schaden sp_rename(wie in der Antwort von @ Peter ausgeführt ), aber es wäre nur eine oberflächliche Änderung. Einer der Hauptgründe , eine Namenskonvention haben , ist für die Wartung, das so , wenn Sie benötigen ALTERoder DROPdas Objekt später, werden Sie zu schreiben Abfragen nicht brauchen , um herauszufinden , was es ist , und dann verketten , dass in dynamischer SQL. Aber diese Sorge ist hier nicht relevant, da es sowieso keine Möglichkeit gibt ALTERoder DROPsie.

Außerdem ist jede Namensänderung, die über vorgenommen wird sp_rename, nur von kurzer Dauer, da bei jeder Änderung ALTER FUNCTIONdie Einschränkungen gelöscht und neu erstellt werden und ihnen daher neu generierte Objektnamen zugewiesen werden. Dies könnte programmgesteuert mit einem DDL-Trigger behandelt werden, der CREATE FUNCTION, ALTER FUNCTIONund CREATE TYPEAnweisungen erfasst , aber das Endergebnis dieser Bemühungen wird nicht sein, dass Ihr Leben einfacher ist ;-). Es wäre nur sein , dass von der Auswahl sys.objects, sys.indexesund sys.key_constraintssieht „sauberen“.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.