在参数化查询中使用 CONVERT

Using CONVERT in a parameterised query

我有一些与 Oracle 数据库交互的 java 代码,正在将其转换为与 SQL 服务器一起工作。

密码是:

String parameterisedSQL = "INSERT INTO T(a,b) VALUES (?,?)";
try (Connection con = DriverManager.getConnection(connectionString, databaseUser, databasePassword);
PreparedStatement stmt = con.prepareStatement(parameterisedSQL);)
{       
    stmt.setString(0,"test");
    stmt.setString(1,"CONVERT(DATE, '20201230', 112)");

    stmt.executeUpdate();
    return true;
} 

很明显,当它是 Oracle 代码时,代码显示为 stmt.setString(1,"TO_DATE('20201230','YYYYMMDD')");

针对 Oracle 数据库的 Oracle 代码工作正常,但现在我是 运行 针对 SQL 服务器数据库的 SQL 服务器代码,我得到一个异常

Conversion failed when converting date and/or time from character string

我由此假设 SQL 服务器没有将 CONVERT 正确解析为参数。有什么办法让它做到这一点? (我的代码实际上比显示的更通用,所以很难使用.setDate,等等)

传递函数的方式解释如下:

INSERT INTO T(a,b) VALUES ('test', 'CONVERT(DATE, '20201230', 112)')

这显然是错误的,因为您试图在 date 列中插入值 'CONVERT(DATE, '20201230', 112)'

你应该这样做:

String parameterisedSQL = "INSERT INTO T(a,b) SELECT ?, CONVERT(DATE, ?, 112)";

和:

stmt.setString(1,"test");
stmt.setString(2,"20201230");

索引基于 1。

@forpas 已经给出了详细的回答

此外,根据您的情况,在插入 table 之前不需要转换短日期格式 (ISO8601)。可以直接插入。

About ISO8601 date format

ISO 8601 Description YYYY-MM-DD

YYYYMMDD Same as the SQL standard. This format is the only format defined as an international standard.

declare @TABLE table(T date)

insert into @TABLE (T) VALUES('20201230')

SELECT * FROM @table

对于你的情况,

stmt.setString(0,"test");
stmt.setString(1,"20201230");

问题和其他两个答案都是 sub-optimal。您不应该将日期值作为字符串发送到数据库。您应该将其作为日期值发送。

在这种情况下,由于它是一个 date-only 值,没有时间部分,您可以使用 java.sql.Datejava.time.LocalDate,具体取决于 JDBC 的功能driver.

另请注意,JDBC API 中的参数索引为 1-base。

// Old code: Wrong
stmt.setString(0,"test");
stmt.setString(1,"CONVERT(DATE, '20201230', 112)");

// Using java.sql.Date
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
stmt.setString(1, "test");
stmt.setDate(2, new java.sql.Date(fmt.parse("20201230")));

// Using java.time.LocalDate
DateTimeFormatter fmt = new DateTimeFormatter.ofPattern("uuuuMMdd");
stmt.setString(1, "test");
stmt.setObject(2, LocalDate.parse("20201230", fmt));