What is dynamic SQL?

后端 未结 9 2242
暗喜
暗喜 2020-12-05 02:28

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

9条回答
  •  無奈伤痛
    2020-12-05 03:04

    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)

提交回复
热议问题