什么是动态SQL?

发布于 2024-10-02 01:24:39 字数 677 浏览 1 评论 0原文

我刚刚问了一个与 SQL 相关的问题,第一个答案是:“这是动态 SQL 的最佳选择。

因为我从未听说过动态 SQL 之前,我立即在这个网站和网络上搜索它是什么。维基百科没有此标题的文章。第一个谷歌结果都指向用户论坛,人们在其中询问或多或少相关的问题。

但是,我没有找到“动态 SQL”的明确定义。这是供应商特定的东西吗?我使用MySQL,但我在MySQL手册中没有找到参考(只有问题,大部分没有答案,在MySQL用户论坛中)。

另一方面,我发现了许多对存储过程的引用。尽管我从未使用过任何存储过程,但我对存储过程的概念有了更好的了解。这两个概念有什么关系?它们是同一件事还是一个使用另一个?

基本上,对于刚接触动态 SQL 概念的人来说,需要的是对动态 SQL 的简单介绍。

PS:如果您愿意,可以尝试回答我上一个引发此问题的问题:SQL:我们如何使 table1 JOIN table2 ON table1 字段中给出的表?

I just asked an SQL related question, and the first answer was: "This is a situation where dynamic SQL is the way to go."

As I had never heard of dynamic SQL before, I immediately searched this site and the web for what it was. Wikipedia has no article with this title. The first Google results all point to user forums where people ask more or less related questions.

However, I didn't find a clear definition of what a 'dynamic SQL' is. Is it something vendor specific? I work with MySQL and I didn't find a reference in the MySQL handbook (only questions, mostly unanswered, in the MySQL user forums).

On the other hand, I found many references to stored procedures. I have a slightly better grasp of what stored procedures are, although I have never used any. How are the two concepts related? Are they the same thing or does one uses the other?

Basically, what is needed is a simple introduction to dynamic SQL for someone who is new to the concept.

P.S.: If you feel like it, you may have a go at answering my previous question that prompted this one: SQL: How can we make a table1 JOIN table2 ON a table given in a field in table1?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

夏有森光若流苏 2024-10-09 01:24:39

动态 SQL 仅仅是动态构建查询的地方 - 对于某些供应商,您可以在一个存储过程中构建动态查询的文本,然后执行生成的 SQL。在其他情况下,该术语仅指客户端代码做出的决定(这至少是供应商中立的)

Dynamic SQL is merely where the query has been built on the fly - with some vendors, you can build up the text of the dynamic query within one stored procedure, and then execute the generated SQL. In other cases, the term merely refers to a decision made by code on the client (this is at least vendor neutral)

欢你一世 2024-10-09 01:24:39

其他答案已经定义了动态 SQL 是什么,但我没有看到任何其他答案试图描述我们有时需要使用它的原因。 (我的经验是 SQL Server,但我认为其他产品在这方面通常是相似的。)

当您替换查询中无法使用其他方法替换的部分时,动态 SQL 非常有用。

例如,每次调用如下查询时:

SELECT OrderID, OrderDate, TotalPrice FROM Orders WHERE CustomerID = ?? 

您将为 CustomerID 传递不同的值。这是最简单的情况,可以通过使用参数化查询或接受参数的存储过程等来解决。

一般来说,应避免使用动态 SQL,而应使用参数化查询,因为性能和安全原因。 (尽管供应商之间的性能差异可能很大,甚至产品版本甚至服务器配置之间的性能差异可能也很大)。

其他查询可能使用参数来执行,但可能更简单为动态 SQL:

SELECT OrderID, OrderDate, TotalPrice FROM Orders 
WHERE CustomerID IN (??,??,??)

如果您始终有 3 个值,则这就像第一个。但如果这是一个可变长度列表怎么办?可以使用参数来完成,但可能非常困难。怎么样:

SELECT OrderID, OrderDate, TotalPrice FROM Orders WHERE CustomerID = ??
ORDER BY ??

这不能直接替换,您可以在 ORDER BY 中使用一个巨大复杂的 CASE 语句来显式列出所有可能的字段,这可能实用也可能不实用,具体取决于可用于排序的字段数量。

最后,有些查询根本无法使用任何其他方法完成。

假设您有一堆 Orders 表(并不是说这是一个很棒的设计),但您可能会发现自己希望可以做一些事情就像:

SELECT OrderID, OrderDate, TotalPrice FROM ?? WHERE CustomerID = ??

使用任何其他方法都无法完成此操作。在我的环境中,我经常遇到如下查询:

SELECT (programatically built list of fields)
FROM table1 INNER JOIN table2
(Optional INNER JOIN to table3)
WHERE (condition1)
AND (long list of other optional WHERE clauses)

再次强调,并不是说这一定是很棒的设计,但这些类型的查询非常需要动态 SQL。

希望这有帮助。

Other answers have defined what dynamic SQL is, but I didn't see any other answers that attempted to describe why we sometimes need to use it. (My experience is SQL Server, but I think other products are generally similar in this respect.)

Dynamic SQL is useful when you are replacing parts of a query that can't be replaced using other methods.

For example, every time you call a query like:

SELECT OrderID, OrderDate, TotalPrice FROM Orders WHERE CustomerID = ?? 

you will be passing in a different value for CustomerID. This is the simplest case, and one that can by solved using a parameterized query, or a stored procedure that accepts a parameter, etc.

Generally speaking, dynamic SQL should be avoided in favor of parameterized queries, for performance and security reasons. (Although the performance difference probably varies quite a bit between vendors, and perhaps even between product versions, or even server configuration).

Other queries are possible to do using parameters, but might be simpler as dynamic SQL:

SELECT OrderID, OrderDate, TotalPrice FROM Orders 
WHERE CustomerID IN (??,??,??)

If you always had 3 values, this is as easy as the first one. But what if this is a variable-length list? Its possible to do with parameters, but can be very difficult. How about:

SELECT OrderID, OrderDate, TotalPrice FROM Orders WHERE CustomerID = ??
ORDER BY ??

This can't be substituted directly, you can do it with a huge complicated CASE statement in the ORDER BY explicitly listing all possible fields, which may or may not be practical, depending on the number of fields available to sort by.

Finally, some queries simply CAN'T be done using any other method.

Let's say you have a bunch of Orders tables (not saying this is great design), but you might find yourself hoping you can do something like:

SELECT OrderID, OrderDate, TotalPrice FROM ?? WHERE CustomerID = ??

This can't be done using any other methods. In my environment, I frequently encounter queries like:

SELECT (programatically built list of fields)
FROM table1 INNER JOIN table2
(Optional INNER JOIN to table3)
WHERE (condition1)
AND (long list of other optional WHERE clauses)

Again, not saying that this is necessarily great design, but dynamic SQL is pretty much required for these types of queries.

Hope this helps.

银河中√捞星星 2024-10-09 01:24:39

动态 SQL 只是在执行之前动态组合的 SQL 语句。例如,以下 C#(使用参数化查询):

var command = new SqlCommand("select * from myTable where id = @someId");
command.Parameters.Add(new SqlParameter("@someId", idValue));

可以使用动态 sql 重写为:

var command = new SqlCommand("select * from myTable where id = " + idValue);

但请记住,动态 SQL 很危险,因为它很容易允许 SQL 注入攻击。

Dynamic SQL is simply a SQL statement that is composed on the fly before being executed. For example, the following C# (using a parameterized query):

var command = new SqlCommand("select * from myTable where id = @someId");
command.Parameters.Add(new SqlParameter("@someId", idValue));

Could be re-written using dynamic sql as:

var command = new SqlCommand("select * from myTable where id = " + idValue);

Keep in mind, though, that Dynamic SQL is dangerous since it readily allows for SQL Injection attacks.

半衾梦 2024-10-09 01:24:39

动态 SQL 是在运行时根据字符串构建的 SQL。动态设置过滤器或其他东西很有用。

一个例子:

declare @sql_clause varchar(1000)  
declare @sql varchar(5000)   


set @sql_clause = ' and '    
set @sql = ' insert into #tmp  
 select   
   *
from Table 
where propA = 1 '    

if @param1 <> ''    
begin    
   set @sql = @sql + @sql_clause + ' prop1 in (' + @param1 + ')'    
end    
if @param2 <> ''    
begin    
   set @sql = @sql + @sql_clause + ' prop2 in (' + @param2 + ')'    
end 

exec(@sql)

Dynamic SQL is a SQL built from strings at runtime. It is useful to dynamically set filters or other stuff.

An example:

declare @sql_clause varchar(1000)  
declare @sql varchar(5000)   


set @sql_clause = ' and '    
set @sql = ' insert into #tmp  
 select   
   *
from Table 
where propA = 1 '    

if @param1 <> ''    
begin    
   set @sql = @sql + @sql_clause + ' prop1 in (' + @param1 + ')'    
end    
if @param2 <> ''    
begin    
   set @sql = @sql + @sql_clause + ' prop2 in (' + @param2 + ')'    
end 

exec(@sql)
你与清晨阳光 2024-10-09 01:24:39

这正是 Rowland 提到的。为了详细说明这一点,请使用以下 SQL:

Select * from table1 where id = 1

我不确定您使用哪种语言连接到数据库,但如果我使用 C#,动态 SQL 查询的示例将如下所示:

string sqlCmd = "Select * from table1 where id = " + userid;

您想要避免使用动态 SQL,因为如果查询太大,保持代码完整性会变得有点麻烦。另外,非常重要的是,动态 SQL 很容易受到 SQL 注入攻击。

如果您使用的是 SQL Server,则编写上述语句的更好方法是使用参数。

It is exactly what Rowland mentioned. To elaborate on that a bit, take the following SQL:

Select * from table1 where id = 1

I am not sure which language you are using to connect to the database, but if I were to use C#, an example of a dynamic SQL query would be something like this:

string sqlCmd = "Select * from table1 where id = " + userid;

You want to avoid using dynamic SQL, because it becomes a bit cumbersome to keep integrity of the code if the query get too big. Also, very important, dynamic SQL is susceptible to SQL injection attacks.

A better way of writing the above statement would be to use parameters, if you are using SQL Server.

为人所爱 2024-10-09 01:24:39

Rowland 是正确的,并且作为附录,除非您正确使用参数(而不是仅从提供的文本内联连接参数值)等)它也可能是一个安全风险。调试起来也很麻烦,等等。

最后,每当你不明智地使用动态 SQL 时,事情就会被释放,孩子会被吃掉。

Rowland is correct, and as an addendum, unless you're properly using parameters (versus just concatonating parameter values inline from provided text, etc.) it can also be a security risk. It's also a bear to debug, etc.

Lastly, whenever you use dynamic SQL unwisely, things are unleashed and children are eaten.

旧街凉风 2024-10-09 01:24:39

对于大多数数据库来说,每个 SQL 查询都是“动态”的,这意味着它是一个由查询优化器在给定输入 SQL 字符串和可能的参数绑定(“绑定变量”)的情况下解释的程序。

静态 SQL

然而,大多数时候,SQL 字符串不是动态构建的,而是静态构建的,无论是在过程语言(如 PL/SQL)中:

FOR rec IN (SELECT * FROM foo WHERE x = 1) LOOP
  --        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "static SQL"
  ..
END LOOP;

还是在客户端/主机语言(如 Java)中,使用 JDBC:

try (ResultSet rs = stmt.executeQuery("SELECT * FROM foo WHERE x = 1")) {
  // "static SQL"                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ..
}

在这两种情况下,SQL 字符串都是“静态的” “在嵌入它的语言中。从技术上讲,它对于 SQL 引擎来说仍然是“动态的”,它不知道 SQL 字符串是如何构造的,也不知道它是静态 SQL 字符串。

动态 SQL

有时,需要在给定一些输入参数的情况下动态构造 SQL 字符串。例如,在某些情况下,上述查询可能根本不需要任何谓词。

然后,您可以选择继续动态构造字符串,例如在 PL/SQL 中:

DECLARE
  TYPE foo_c IS REF CURSOR;
  v_foo_c foo_c;
  v_foo foo%ROWTYPE;
  sql VARCHAR2(1000);
BEGIN
  sql := 'SELECT * FROM foo';

  IF something THEN
    sql := sql || ' WHERE x = 1'; -- Beware of syntax errors and SQL injection!
  END IF;

  OPEN v_foo_c FOR sql;
  LOOP
    FETCH v_foo_c INTO v_foo;
    EXIT WHEN v_foo_c%NOTFOUND;
  END LOOP;
END;

或在 Java / JDBC 中:

String sql = "SELECT * FROM foo";
if (something)
    sql += " WHERE x = 1"; // Beware of syntax errors and SQL injection!
try (ResultSet rs = stmt.executeQuery(sql)) {
  ..
}

或在 Java 使用像 jOOQ 这样的 SQL 构建器

// No syntax error / SQL injection risk here
Condition condition = something ? FOO.X.eq(1) : DSL.trueCondition();
for (FooRecord foo : DSL.using(configuration)
   .selectFrom(FOO)
   .where(condition)) {
  ..
}

许多语言都有像上面这样的查询构建器库,它们在执行动态 SQL 时最闪耀。

(免责声明:我在 jOOQ 背后的公司工作)

To most databases, every SQL query is "dynamic" meaning that it is a program that is interpreted by the query optimiser given the input SQL string and possibly the parameter bindings ("bind variables").

Static SQL

However, most of the time, that SQL string is not constructed dynamically but statically, either in procedural languages like PL/SQL:

FOR rec IN (SELECT * FROM foo WHERE x = 1) LOOP
  --        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "static SQL"
  ..
END LOOP;

Or in client / host languages like Java, using JDBC:

try (ResultSet rs = stmt.executeQuery("SELECT * FROM foo WHERE x = 1")) {
  // "static SQL"                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ..
}

In both cases, the SQL string is "static" in the language that embeds it. Technically, it will still be "dynamic" to the SQL engine, which doesn't know how the SQL string is constructed, nor that it was a static SQL string.

Dynamic SQL

Sometimes, the SQL string needs to be constructed dynamically, given some input parameters. E.g. the above query might not need any predicate at all in some cases.

You might then choose to proceed to constructing the string dynamically, e.g. in PL/SQL:

DECLARE
  TYPE foo_c IS REF CURSOR;
  v_foo_c foo_c;
  v_foo foo%ROWTYPE;
  sql VARCHAR2(1000);
BEGIN
  sql := 'SELECT * FROM foo';

  IF something THEN
    sql := sql || ' WHERE x = 1'; -- Beware of syntax errors and SQL injection!
  END IF;

  OPEN v_foo_c FOR sql;
  LOOP
    FETCH v_foo_c INTO v_foo;
    EXIT WHEN v_foo_c%NOTFOUND;
  END LOOP;
END;

Or in Java / JDBC:

String sql = "SELECT * FROM foo";
if (something)
    sql += " WHERE x = 1"; // Beware of syntax errors and SQL injection!
try (ResultSet rs = stmt.executeQuery(sql)) {
  ..
}

Or in Java using a SQL builder like jOOQ

// No syntax error / SQL injection risk here
Condition condition = something ? FOO.X.eq(1) : DSL.trueCondition();
for (FooRecord foo : DSL.using(configuration)
   .selectFrom(FOO)
   .where(condition)) {
  ..
}

Many languages have query builder libraries like the above, which shine most when doing dynamic SQL.

(Disclaimer: I work for the company behind jOOQ)

脸赞 2024-10-09 01:24:39

这是供应商特定的东西吗?

SQL-92 标准有一整章关于动态 SQL(第 17 章),但它仅适用于完整的 SQL-92,而且据我所知还没有供应商实现了它。

Is it something vendor specific?

The SQL-92 Standard has a whole chapter on dynamic SQL (chapter 17) but it only applies to FULL SQL-92 and I know of no vendor that has implemented it.

生活了然无味 2024-10-09 01:24:39

我认为这意味着您应该在执行查询之前动态构建查询。对于您的其他问题,这意味着您应该首先选择您需要的表名称,然后使用您的编程语言构建第二个查询来执行您想要的操作(您在另一个问题中想要执行的操作不可能像您想要的那样直接执行) )。

I think what's meant is that you should build the query dynamically before executing it. For your other questions this means that you should select the table name you need first and the use your programming language to build a second query for doing what you want (what you want to do in the other question isn't possible directly like you want).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文