gar*_*eth 20 sql-server-2008 t-sql
原谅我,我是一名已经转向 SQL 世界的开发人员。我以为我可以通过添加变量来改进一些 SQL,但它并没有像我预期的那样运行。有人能告诉我为什么这不起作用吗?我不想解决问题,我想知道为什么这不像我想象的那样工作,因为我确信有一个很好的理由,但目前它并没有跳出来。
DECLARE @DatabaseName varchar(150)
SET @DatabaseName = 'MyAmazingDatabaseName'
CREATE DATABASE @DatabaseName
GO
USE @DatabaseName
GO
Run Code Online (Sandbox Code Playgroud)
Bob*_*mes 21
根据变量的书籍在线页面
变量只能在表达式中使用,不能代替对象名称或关键字。要构造动态 SQL 语句,请使用 EXECUTE。
例如,如果您在 where 子句中使用了您的变量,它将以您期望的方式工作。至于为什么,我认为这与解析器无法评估变量并因此检查是否存在有关。执行时,首先解析查询的语法和对象,然后,如果解析成功,则执行查询,此时变量将被设置。
DECLARE @name varchar(20);
SET @name = 'test';
CREATE TABLE [#tmp]([val] varchar(10));
insert into #tmp
values('test')
SELECT *
FROM [#tmp]
WHERE [val] = @name;
Run Code Online (Sandbox Code Playgroud)
gra*_*j42 18
在 SQL 语句中使用变量的限制源于 SQL 的体系结构。
SQL 语句的处理分为三个阶段:
SQL Server 对程序员隐藏了准备步骤,并且执行速度比 Oracle 和 DB2 等更传统的数据库快得多。出于性能原因,SQL 可能会花费大量时间来确定最佳执行计划,但仅在重新启动后第一次遇到该语句时才这样做。
所以在静态 SQL 中,变量只能用在不会使执行计划失效的地方,所以不能用于表名、列名(包括 WHERE 条件中的列名)等。
动态 SQL存在于无法绕过限制的情况下,并且程序员知道执行时间会稍长一些。动态 SQL 容易受到恶意代码注入,所以要小心!
如您所见,“为什么”问题需要不同类型的答案,包括语言的历史基本原理和基本假设,我不确定我是否真的能做到这一点。
SQL MVP Erland Sommarskog 的这篇综合性文章确实试图提供一些基本原理以及机制:
缓存查询计划
您在 SQL Server 中运行的每个查询都需要一个查询计划。当您第一次运行查询时,SQL Server 会为其构建一个查询计划——或者按照术语的说法——它会编译查询。SQL Server 将计划保存在缓存中,下次运行查询时,将重复使用该计划。
这(和安全性,见下文)可能是最大的原因。
SQL 操作的前提是查询不是一次性操作,而是会被反复使用。如果表(或数据库!)实际上没有在查询中指定,它就无法生成和保存执行计划以备将来使用。
是的,不是我们运行的每一个查询都会被重用,但这是SQL的默认运行前提,所以“例外”意味着例外。
Erland 列出的其他一些原因(请注意,他明确列出了使用存储过程的优势,但其中许多也是参数化(非动态)查询的优势):
同样,每一个都有一百个细微差别,我不会在这里讨论。