在参数化查询中使用 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)。可以直接插入。
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.Date
或 java.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));
我有一些与 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)。可以直接插入。
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.Date
或 java.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));