通过JDBC发送DEFAULT占位符?

11

通过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,但在另一些批次中则不使用。

在常规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 是一个特殊的占位符实例,因为似乎没有 PreparedStatementsetDefault() 方法。

是否有任何现有的驱动程序支持这个?


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

3
没有标准的方法来做到这一点。据我所知,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。我不知道是否有任何驱动程序目前支持这样的解决方法。

1

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


DEFAULT 不仅仅适用于 PostgreSQL。请参见:http://sqlfiddle.com/#!2/d9dca,http://sqlfiddle.com/#!4/d9dca,http://sqlfiddle.com/#!6/d9dca。(MySQL、Oracle 和 MS-SQL)。顺便说一句,这是我唯一能够在每个数据库上运行完全相同的代码的时候。我会称它为占位符关键字。 - Craig Ringer
@CraigRinger 每天都会学到新东西,谢谢!没想到还会在其他 RDBMs 上找到它。不太确定它应该被称为什么,但如果我理解正确,这个事实并不改变我的回答的本质——它是一个语法元素,而不是一个值,因此它不能被绑定。 - Mureinik
2
JDBC有PreparedStatement.setNull,而NULL也只能算是一个“值”。我一直希望有一种标准但晦涩的方法来处理DEFAULT,但看起来是“没有”的。 - Craig Ringer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接