2016-05-25 8 views
0

Meine gespeicherte Prozedur darf eine beliebige Zeichenfolge @String als varchar oder mit maximal 128 Zeichen Länge übergeben werden.Überprüfen, ob ein vorgeschlagener T-SQL-Objektname gültig ist oder in eckige Klammern eingeschlossen werden muss

Die gespeicherte Prozedur muss den Wert @String als Objektnamen verwenden, d. H. Den Namen einer Tabelle, eines Felds, einer Sicht oder ähnlichem.

Wie kann ich feststellen, ob der angegebene Wert @String ein gültiger Objektname ist - dh kein reserviertes Wort ist und keine ungültigen Zeichen enthält - oder wenn es ein Gehäuse innerhalb benötigt (und jegliches Entkommen) eckige Klammern um machen es ein gültiger Objektname.

Zum Beispiel, "X", "Foo" und "C: \ Temp \ X.csv" sind gültige Objektnamen (ja, ich habe erfolgreich "C: \ Temp \ X.csv" wie sie ist verwendet) und kann unmodifiziert verwendet werden, während "Select", "AB] C" und "1_ABC" nicht gültig sind und in "[Select]", "[AB]] C" und "[1_ABC ] "

Ich würde eine Lösung bevorzugen, die nicht einfach versucht, ein Objekt mit diesem Namen zu erstellen und dann überprüft, ob es funktioniert hat.

Bevorzugt werden Antworten, die über eine größere Anzahl von SQL Server-Versionen als nur die neueste Version anwendbar sind, und kürzerer, weniger komplexer Code wird gegenüber längerem, komplexeren Code bevorzugt.

Als ein Beispiel für das Problem, das mich dazu gebracht, diese Frage zu stellen, kann meine SP @Name geben werden, die „C: \ Temp \ X.csv“ sein könnten oder „ABC“ oder „SELECT“ oder was auch immer. Mein SP erstellt dann eine Tabelle, füllt sie und dann (so dass ich nicht dynamisches SQL verwenden muss) ändert ihren Namen zu @Name mit sp_rename. Ich brauche QUOTENAME(@Name) wo @Name = "SELECT", aber nicht in den anderen beiden Fällen, (in den SSMS Object Explorer) Tabellen "dbo.C: \ Temp \ X.csv", "dbo.ABC" und "dbo .WÄHLEN". Ich muss auch überprüfen, ob diese Objekte vorhanden sind, bevor ich den Rest des SP ausführe, und wenn ich QUOTENAME "C: \ Temp \ X.csv", bevor ich es als der neue Name an sp_rename übergeben, erscheint es in der SSMS-Objekt-Explorer als "dbo. [C: \ Temp \ X.csv]", und ich muss IF OBJECT_ID('[[C:\Temp\X.csv]]]') IS NOT NULL verwenden, um erfolgreich festzustellen, dass es existiert, nichtIF OBJECT_ID('[C:\Temp\X.csv]') IS NOT NULL.

+1

Warum sich Sorgen machen, ob * es * beigefügt werden muss, wenn Sie es einfach an 'QUOTENAME' übergeben können und mit dem Rest Ihrer Arbeit fortfahren. Sicher, manchmal hat es * unnötige * Klammern hinzugefügt, aber ist das wirklich ein Problem? –

+0

@Damien_The_Unbeliever, ja, wenn ich 'QUOTENAME'" C: \ Temp \ X.csv "bekomme ich" [C: \ Temp \ X.csv] ", aber ich muss * beziehen * auf" [[C: \ Temp \ X.csv]]] um * das * resultierende Objekt zu verwenden. Wenn ich es nicht "QUOTENAME", kann ich * verweisen * als "[C: \ Temp \ X.csv]" oder "C: \ Temp \ X.csv". –

+0

Eh? Ich bin nicht sicher, was Sie meinen, indem Sie in Ihrem Kommentar verweisen/verwenden - sobald Sie den Namen zitiert haben, ist das ein Name, den Sie für den Rest Ihres Codes verwenden können. Sie müssen den Wert nicht erneut codieren. Vielleicht, wenn Sie ein kurzes Beispiel Ihrer Verwendung hinzufügen könnten? –

Antwort

2

Bei Verwendung von sp_rename muss der neue Name für das Objekt niemals maskiert werden, verwenden Sie einfach den übergebenen Wert @Name.

Es stimmt, dass OBJECT_ID manchmal einen entflohenen Namen wollen könnte, aber da ein direkter Test, der verfügbar ist, wieder, erfordert nicht entkommen, würde ich vorschlagen, wie Sie den Test durch, dass statt:

IF EXISTS(SELECT * from sys.tables where name = @Name) 
... 

(Oder Sie können stattdessen sys.objects abfragen, bis zu Ihnen)

Ich hatte ursprünglich gedacht, dass Sie den Namen in dynamischem SQL verwendeten. In dynamischen SQL-Kontexten würde ich vorschlagen, den Namen immer unter Verwendung von QUOTENAME zu entschlüsseln, anstatt zu versuchen, zu ermitteln, ob eine Entwurzelung erforderlich ist.

1

Dieser Code hilft möglicherweise bei der Verwendung von QUOTENAME. Es wird nicht in sp_rename verwendet.

CREATE PROCEDURE TestObjectNames 
    @Name SYSNAME 
AS 

DECLARE @SQL NVARCHAR(MAX); 

-- Create temporary table 
CREATE TABLE Temp (ID INT, Name SYSNAME); 
-- Load temporary table 
INSERT INTO Temp SELECT database_id, name FROM sys.databases; 
-- Check existance of table 
IF NOT EXISTS(SELECT * FROM sys.tables WHERE name = @Name) 
    -- Rename table (Don't use QUOTENAME) 
    EXEC sp_rename 'Temp', @Name;; 
-- Fetch object id of new table (Use QUOTENAME) 
SELECT OBJECT_ID(QUOTENAME(@Name)) AS NewTableID; 
-- Select from table dynamically (Use QUOTENAME) 
SET @SQL = 'SELECT COUNT(*) AS NewTableCount FROM ' + QUOTENAME(@Name); 
EXEC sp_executesql @SQL; 
-- Drop new table dynamically (Use QUOTENAME) 
SET @SQL = 'DROP TABLE ' + QUOTENAME(@Name); 
EXEC sp_executesql @SQL; 
GO 

EXEC TestObjectNames 'SELECT'; 
EXEC TestObjectNames 'C:\Temp\X.csv'; 
EXEC TestObjectNames 'AB]C'; 
EXEC TestObjectNames '1_ABC'; 
EXEC TestObjectNames 'ABC'; 
Verwandte Themen