【问题标题】:Sending the DEFAULT placeholder via JDBC?通过 JDBC 发送 DEFAULT 占位符?
【发布时间】:2014-09-11 05:21:09
【问题描述】:

有什么方法可以通过 JDBC 显式发送 DEFAULT 占位符,就像在 INSERT INTO sometables VALUES (blah, DEFAULT) 中一样? (我几乎可以肯定答案是否定的,但我正在寻找 JDBC 专家的确认)。

假设你有一个 PreparedStatement 喜欢:

INSERT INTO mytable(a, b) VALUES (?, ?)

表:

CREATE TABLE mytable (
    a integer,
    b integer default some_function()
);

并且您想在批处理中的某些执行中使用数据库集 DEFAULT for mytable.b 而不是其他执行。

在常规 SQL 中你会写:

INSERT INTO mytable(a, b) VALUES (1, 42)
INSERT INTO mytable(a, b) VALUES (2, DEFAULT);
...

当然也可以:

INSERT INTO mytable(a, b) VALUES (1, 42)
INSERT INTO mytable(a) VALUES (2);

...但是您不能通过 JDBC 执行此操作。 setString("DEFAULT") 当然不会发送 DEFAULT 关键字,只会发送字符串文字 'DEFAULT'

有没有办法在任何广泛使用的驱动程序中设置一个表示DEFAULT 的占位符参数?

我看不到使用标准 API 和规范的方法。

我在想象这样的事情:

pstmt.setObject(2, Postgresql.DEFAULT, Types.OTHER);

其中Postgresql.DEFAULT 是一个特殊的占位符实例,因为PreparedStatement 似乎没有setDefault() 方法。

任何现有的驱动程序都支持这个吗?

【问题讨论】:

  • 如果您需要默认值的地方很少,您可以只拥有两个副本:insert into mytable(a b) values (?, ?)insert into mytable(a b) values (?, ?)
  • 解决方法是先执行查询以获取列默认值,然后将它们作为值包含在 PreparedStatement 中: SELECT COLUMN_NAME, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='dbName ' AND TABLE_NAME='tableName';
  • @AaronDuniganAtLee 如果默认值是文字,这将起作用,但如果默认值是表达式,则可能会产生令人惊讶的结果 - 您不能包含任意 SQL 表达式作为绑定参数。

标签: java sql jdbc


【解决方案1】:

没有标准的方法来做到这一点。据我所知,SQL 标准不支持通过参数声明使用DEFAULT 的机制。 SQL 标准似乎假定每个INSERT 都是为特定目的而设计的。所以声明DEFAULT 只能在插入语句本身中完成,而不是作为参数的值。在这类决策中,JDBC 规范通常遵循 SQL 标准。

您目前拥有的唯一方法是在 JDBC 驱动程序中创建一个特定于供应商的方法,例如您在问题本身中指定的方法,但您也可以考虑类似:

澄清一下:下面是一个驱动程序实现如何解决它的示例,它实际上并不是这样工作的。

使用setNull(int, int)

setNull(idx, PostgresTypes.DEFAULT_VALUE)

或使用setNull(int, int, String)

setNull(idx, Types.<correct-field-type>, Postgres.DEFAULT_VALUE_MARKER)

然而,这假设 PostgreSQL 实际上有一个通过参数指定 DEFAULT 的方法,或者驱动程序实现将为每组接收到的参数解析并重新创建语句,以便它可以声明一个文字 DEFAULT

不知道目前有没有驱动支持这种变通方法。

【讨论】:

    【解决方案2】:

    default 不是一个值文字 - 它是一个伪列(或者至少我希望它们在 postgres 中是这样称呼的)。由于它不是一个值,而是insert 语法的一部分,所以它不能绑定到占位符,就像表名不能一样。

    【讨论】:

    • DEFAULT 不仅仅是 PostgreSQL。请参阅:sqlfiddle.com/#!2/d9dcasqlfiddle.com/#!4/d9dcasqlfiddle.com/#!6/d9dca。 (MySQL、Oracle 和 MS-SQL)。顺便说一句,这是我唯一一次能够简单地在每个代码上运行完全相同的代码。我称之为占位符关键字。
    • @CraigRinger 你每天都能学到新东西,谢谢!没想到在其他 RDBM 上也能找到。不太确定它应该叫什么,但是 IIUC,这个事实并没有改变我回答的本质——它是一个语法元素,而不是一个值,所以它不能被绑定。
    • JDBC 有PreparedStatement.setNull,而NULL 也只能说是一个“价值”。我一直希望有一种标准但晦涩难懂的方式来处理DEFAULT,但它看起来像“不”。
    猜你喜欢
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    • 1970-01-01
    • 2019-01-07
    • 2015-04-14
    • 2017-02-10
    相关资源
    最近更新 更多