为什么准备好的语句不允许字段和表名作为参数?

时间:2018-07-28 19:41:24

标签: database hibernate jdbc pdo

DBMS仅允许将值用作准备好的语句的参数。但是,准备好的语句不允许使用表,列和字段名称。例如:

String sql = "Select * from TABLE1 order by ?";
PreparedStatement st = conn.prepareStatement(sql);
st.setString(1, "column_name_1");

不允许这样的陈述。 DBMS在准备好的语句中不实现文件名的原因是什么?

1 个答案:

答案 0 :(得分:2)

我基本上知道两个原因:

  1. 尽管每个数据库系统的详细信息有所不同,但从概念上讲,准备语句时,将对其进行编译并检查其正确性(是否存在所有表和列)。服务器生成一个计划,该计划描述要访问的表,要检索的字段,要使用的索引等。

    这意味着在准备时,数据库系统必须知道它需要访问哪些表和字段,因此无法对表和字段进行参数化。而且,即使在技术上可行的情况下,它也效率不高,因为语句编译需要推迟到执行之后,从根本上抛弃了使用准备好的语句的主要原因之一:可重复使用的查询计划以提高性能。

    并考虑一下:如果允许对表名和字段名进行参数化,为什么不对函数名,查询片段等进行参数化?

  2. 不允许对象的参数化可防止歧义。例如,在带有where column1 = ?的查询中,如果将参数设置为peter,那将是列名还是字符串值?很难确定并避免歧义性会使API变得更难使用,而几乎不允许使用这种参数化的用例(根据我的经验,对这种参数化的需求几乎总是源自不良的数据库设计)

允许对象的参数化几乎等同于仅动态生成查询并执行查询(另请参见第1点),所以为什么不放弃附加的复杂性并禁止对象的参数化。