it-swarm.com.de

Warum kann ich in T-SQL keine Variablen verwenden, wie ich es mir vorstellen kann?

Verzeihen Sie mir, ich bin ein Entwickler, der in die Welt von SQL gewechselt ist. Ich dachte, ich könnte etwas SQL durch Hinzufügen von Variablen verbessern, aber es funktionierte nicht wie erwartet. Kann mir jemand sagen, warum das nicht funktioniert? Ich möchte nicht herumarbeiten, ich möchte wissen, warum dies nicht so funktioniert, wie ich es mir vorstelle, da ich sicher bin, dass es einen guten Grund gibt, aber momentan springt es mir nicht auf.

DECLARE @DatabaseName varchar(150)
SET @DatabaseName = 'MyAmazingDatabaseName'

CREATE DATABASE @DatabaseName
GO

USE @DatabaseName
GO
18
gareth

Auf der Online-Seite Bücher für Variablen

Variablen können nur in Ausdrücken verwendet werden, nicht anstelle von Objektnamen oder Schlüsselwörtern. Verwenden Sie EXECUTE, um dynamische SQL-Anweisungen zu erstellen.

Es würde so funktionieren, wie Sie es erwartet hatten, wenn Sie beispielsweise Ihre Variable in einer where-Klausel verwendet hätten. Was den Grund angeht, würde ich denken, dass dies etwas damit zu tun hat, dass der Parser die Variable nicht auswerten und somit auf Existenz prüfen kann. Bei der Ausführung wird die Abfrage zuerst nach Syntax und Objekten analysiert. Bei erfolgreicher Analyse wird die Abfrage dann ausgeführt, an welchem ​​Punkt die Variable festgelegt wird.

DECLARE @name varchar(20);
SET @name = 'test';

CREATE TABLE [#tmp]([val] varchar(10));

insert into #tmp
values('test')

SELECT *
FROM [#tmp]
WHERE [val] = @name;
20
Bob Klimes

Die Einschränkungen bei der Verwendung von Variablen in SQL-Anweisungen ergeben sich aus der Architektur von SQL.

Die Verarbeitung einer SQL-Anweisung besteht aus drei Phasen:

  1. Vorbereitung - Die Anweisung wird analysiert und ein Ausführungsplan wird kompiliert, der angibt, auf welche Datenbankobjekte zugegriffen wird, wie auf sie zugegriffen wird und wie sie zusammenhängen. Der Ausführungsplan wird im Plan-Cache gespeichert.
  2. Bindung - Alle Variablen in der Anweisung werden durch tatsächliche Werte ersetzt.
  3. Ausführung - Der zwischengespeicherte Plan wird mit den gebundenen Werten ausgeführt.

SQL Server verbirgt den Vorbereitungsschritt vor dem Programmierer und führt ihn viel schneller aus als herkömmliche Datenbanken wie Oracle und DB2. Aus Leistungsgründen verbringt SQL möglicherweise viel Zeit damit, einen optimalen Ausführungsplan zu ermitteln, dies jedoch nur beim ersten Auftreten der Anweisung nach einem Neustart.

In statisches SQL dürfen Variablen nur an Stellen verwendet werden, an denen sie den Ausführungsplan nicht ungültig machen, also nicht für Tabellennamen, Spaltennamen (einschließlich Spaltennamen in WHERE-Bedingungen) usw.

Dynamic SQL existiert für die Fälle, in denen die Einschränkungen nicht umgangen werden können und der Programmierer weiß, dass die Ausführung etwas länger dauern wird. Dynamisches SQL kann anfällig für die Injektion von bösartigem Code sein. Seien Sie also vorsichtig!

17
grahamj42

Wie Sie sehen können, erfordert die "Warum" -Frage eine andere Art von Antwort, einschließlich historischer Gründe und zugrunde liegender Annahmen für die Sprache. Ich bin mir nicht sicher, ob ich dieser Gerechtigkeit wirklich gerecht werden kann.

Dieser umfassende Artikel von SQL MVP Erland Sommarskog versucht, neben der Mechanik einige Gründe zu liefern:

Der Fluch und der Segen von Dynamic SQL :

Zwischenspeichern von Abfrageplänen

Für jede Abfrage, die Sie in SQL Server ausführen, ist ein Abfrageplan erforderlich. Wenn Sie eine Abfrage zum ersten Mal ausführen, erstellt SQL Server einen Abfrageplan dafür - oder die Terminologie kompiliert die Abfrage. SQL Server speichert den Plan im Cache. Wenn Sie die Abfrage das nächste Mal ausführen, wird der Plan erneut verwendet.

Dies (und Sicherheit, siehe unten) ist wahrscheinlich der größte Grund.

SQL arbeitet unter der Voraussetzung, dass Abfragen keine einmaligen Vorgänge sind, sondern immer wieder verwendet werden. Wenn die Tabelle (oder die Datenbank!) Nicht tatsächlich in der Abfrage angegeben ist, kann kein Ausführungsplan für die zukünftige Verwendung erstellt und gespeichert werden.

Ja, nicht jede von uns ausgeführte Abfrage wird wiederverwendet, aber dies ist die Standardbetriebsvoraussetzung von SQL, daher sollen "Ausnahmen" außergewöhnlich sein.

Einige andere Gründe, die Erland auflistet (beachten Sie, dass er die Vorteile der Verwendung von gespeicherte Prozeduren auflistet, aber viele davon sind auch Vorteile parametrisierter (nicht dynamischer) Abfragen):

  • Das Berechtigungssystem : Die SQL-Engine kann nicht vorhersagen, ob Sie die Rechte zum Ausführen einer Abfrage haben, wenn sie die Tabelle (oder Datenbank) nicht kennt. Sie werden gegen operieren. "Berechtigungsketten" mit dynamischem SQL sind ein Problem.
  • Reduzieren des Netzwerkverkehrs : Das Übergeben des Namens des gespeicherten Prozesses und einiger Parameterwerte über das Netzwerk ist kürzer als eine lange Abfrageanweisung.
  • Kapselungslogik : Sie sollten mit den Vorteilen der Kapselungslogik aus anderen Programmierumgebungen vertraut sein.
  • Verfolgen, was verwendet wird : Wenn ich eine Spaltendefinition ändern muss, wie kann ich den gesamten Code finden, der sie aufruft? Systemprozeduren sind vorhanden, um Abhängigkeiten in einer SQL-Datenbank zu finden, jedoch nur, wenn sich der Code in gespeicherten Prozeduren befindet.
  • Einfaches Schreiben von SQL-Code : Die Syntaxprüfung erfolgt beim Erstellen oder Ändern einer gespeicherten Prozedur, sodass hoffentlich weniger Fehler auftreten.
  • Beheben von Fehlern und Problemen : Ein DBA kann die Leistung einzelner gespeicherter Prozeduren viel einfacher verfolgen und messen als sich ständig änderndes dynamisches SQL.

Auch hier hat jede von ihnen hundert Nuancen, auf die ich hier nicht eingehen werde.

7
BradC

Sie müssen dynamisches SQL verwenden

DECLARE @DatabaseName varchar(150) = 'dbamaint'
declare @sqltext nvarchar(max) = N''

set @sqltext = N'CREATE DATABASE '+quotename(@DatabaseName)+ ';'

print @sqltext 

-- once you are happy .. uncomment below
--exec sp_executesql @sqltext
set @sqltext = ''
set @sqltext = N'use '+quotename(@DatabaseName)+ ';'
print @sqltext 
-- once you are happy .. uncomment below
--exec sp_executesql @sqltext

unten ist die Ausgabe von print. Sobald Sie den Kommentar exec sp_executesql @sqltext auskommentieren, werden die Anweisungen tatsächlich ausgeführt ...

CREATE DATABASE [dbamaint];
use [dbamaint];
2
Kin Shah