2009-07-09 2 views
2

Ich bin nach einer einfachen gespeicherten Prozedur, um Tabellen zu löschen. Hier ist mein erster Versuch:Wie parameteriere ich eine gespeicherte T-SQL-Prozedur, die eine Tabelle löscht?

CREATE PROC bsp_susf_DeleteTable (@TableName char) 
AS 
IF EXISTS (SELECT name FROM sysobjects WHERE name = @TableName) 
BEGIN 
DROP TABLE @TableName 
END 

Wenn ich dies in MS Query Analyzer analysieren bekomme ich folgende Fehlermeldung:

Server: Msg 170, Level 15, State 1, Procedure bsp_susf_DeleteTable, Line 6 
Line 6: Incorrect syntax near '@TableName'. 

Welche Art Sinn macht, weil die normalen SQL für eine einzelne Tabelle würden:

Beachten Sie, dass die erste Instanz von tbl_XYZ (in der WHERE-Klausel) einfache Anführungszeichen hat, während die zweite Instanz in der DROP-Anweisung dies nicht tut. Wenn ich eine Variable (@TableName) verwende, kann ich diese Unterscheidung nicht treffen.

Also kann eine gespeicherte Prozedur erstellt werden, um dies zu tun? Oder muss ich die IF EXISTS kopieren ... überall?

Antwort

3

Sie sollten dynamische SQL verwenden können.

Update: Ja, Sie kleiner machen @sql können, war dies nur ein kleines Beispiel. Beachten Sie auch, andere Kommentare über SQL-Injection-Attacken

+0

Dank Wayne - hat gut funktioniert. – dave

+0

Machen Sie @SQL nvarchar (max), da Tabellennamen nvarchar sind. (Eigentlich sysname, aber gleichbedeutend mit nvarchar (irgendeine Zahl, 128 vielleicht?) –

+3

Sie sollten @TableName auch für eckige Klammern entziffern. SQL Server hat einen Befehl, der das für Sie erledigt. Setzen Sie @sql = 'drop table' + QuoteName (@ Tabellenname); –

0

Sie müssen EXEC verwenden, die Abfrage als String auszuführen. Mit anderen Worten, wenn Sie den Tabellennamen übergeben, definieren Sie ein varchar und weisen Sie die Abfrage und Tabellenname, dann führen Sie die Variable, die Sie erstellt haben.

Edit: JEDOCH Ich empfehle nicht, dass da jemand in SQL Pass könnte eher als ein Tablename und führt alle Arten von wunderbaren Problemen. Siehe Sql-Injektion für weitere Informationen.

Ihre beste Wette ist eine parametrisierte Abfrage auf der Client-Seite für diese zu schaffen. Zum Beispiel in C# würde ich so etwas wie:

declare @sql varchar(max) 
if exists (select name from sysobjects where name = @TableName) 
BEGIN 
    set @sql = 'drop table ' + @TableName 
    exec(@sql) 
END 

this helps:

// EDIT 2: on second thought, ignore this code; it probably won't work 
SqlCommand sc = new SqlCommand(); 
sc.Connection = someConnection; 
sc.CommandType = Command.Text; 
sc.CommandText = "drop table @tablename"; 
sc.Parameters.AddWithValue("@tablename", "the_table_name"); 
sc.ExecuteNonQuery(); 
+0

Danke Michael. – dave

+1

Ehrlich, wenn der BESTIMMTE Purpose des gespeicherten Proc ist, eine Arbitrary-Tabelle fallen zu lassen, wie viel schlimmer könnte ein SQL Injecion Angriff sein? Ich meine, warum sollte man einem Sring entgehen, wenn man irgendeinen Tisch in der Datenbank löschen kann, ohne dass ein Hack benötigt wird? – JohnFx

+0

Hmmm ... guter Punkt. Hatte nicht davon. –

2

Persönlich würde ich sehr vorsichtig sein, dies zu tun. Wenn Sie das Gefühl haben, dass Sie es für administrative Zwecke benötigen, stellen Sie bitte sicher, dass die Rechte zur Ausführung dieses Formulars sehr begrenzt sind. Außerdem würde der proc den Tabellennamen und das Datum und den Benutzer in eine Logging-Tabelle kopieren. So weißt du zumindest, wer den falschen Tisch fallen ließ. Sie können auch andere Schutzmaßnahmen wünschen. Zum Beispiel möchten Sie möglicherweise bestimmte Tabellen angeben, die mit diesem Proc nie gelöscht werden können.

Weiterhin wird dies nicht auf alle Tabellen in allen Fällen. Sie können keine Tabelle löschen, der ein Fremdschlüssel zugeordnet ist.

Unter keinen Umständen würde ich einem Benutzer oder irgendjemandem erlauben, dass der Datenbankadministrator diesen Prozess ausführt. Wenn Sie über ein Systemdesign verfügen, bei dem Benutzer Tabellen löschen können, liegt höchstwahrscheinlich etwas drastisch falsch an Ihrem Design vor und sollte überdacht werden.

Verwenden Sie diesen Proc auch nicht, wenn Sie nicht über einen wirklich guten Sicherungszeitplan verfügen und die Wiederherstellung aus Sicherungen durchführen.

+0

Dies sind alles hervorragende Punkte.Meine Situation ist so, dass diese kein Problem sind.Wir haben eine Produktionsdatenbank, die über Nacht kopiert wird, um unsere Berichtsdatenbank zu bilden.Wir führen Berichte mit dieser Kopie aus, um Tabellen mit abgeleiteten Daten (und keine Fremdschlüssel.) Wir löschen nur diese abgeleiteten Tabellen, aber wenn wir etwas versehentlich löschen, ist das egal. – dave

Verwandte Themen