我有以下
DateFormat dformat = new SimpleDateFormat("yyyy-M-d");
dformat.setLenient(false);
Date cin = dformat.parse(cinDate);
和sql函数
create or replace function search(_checkIn date, _checkOut date) returns setof Bookings as $$
declare
r Bookings;
begin
for r in
select * from Bookings
loop
if ((_checkIn between r.checkIn and r.checkOut) or (_checkOut between r.checkIn and r.checkOut)) then
return next r;
end if;
end loop;
return;
end;
$$ language plpgsql;
postgresql的日期格式是标准(默认)
create table Bookings (
id serial,
status bookingStatus not null,
pricePaid money not null,
firstName text,
lastName text,
address text,
creditCard text,
checkOut date not null,
checkIn date not null,
room integer not null,
extraBed boolean not null default false,
foreign key (room) references Rooms(id),
primary key (id)
);
我正在尝试将一个日期解析为函数,因此它可以为我返回一个表,我似乎遇到了日期格式问题(这就是为什么我认为我收到此错误)
org.postgresql.util.PSQLException: ERROR: syntax error at or near "Feb"
所以我想知道如何解决这个问题,我不知道如何正确格式化日期
编辑:
我正在调用这样的查询
try {
String searchQuery = "SELECT * FROM Rooms r where r.id not in (select * from search(" + cin +", " + cout +"))";
PreparedStatement ps = conn.prepareStatement(searchQuery);
rs = ps.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
所以我认为错误是因为我格式化日期的方式是错误的而且postgres不会读取它
答案 0 :(得分:3)
听起来你通过将它们直接连接到字符串来传递参数。这是一个非常糟糕的主意,因为它可能导致SQL注入。永远use PreparedStatement
s与?
占位符一起传递参数,永远不要直接将它们直接连接到查询字符串中(更多的是,你需要'
分隔符)。
你可以拥有类似的东西:
PreparedStatement stmt
= con.prepareStatement("SELECT id FROM Bookings WHERE checkIn=?")
stmt.setDate(1, new java.sql.Date(cin.getTime()));
// ? parameters are indexed from 1
ResultSet results = stmt.executeQuery();
或者,PostgreSQL内部日期转换通常相当不错且灵活。您可以使用PostgreSQL将字符串参数强制转换为日期:
PreparedStatement stmt
= con.prepareStatement("SELECT id FROM Bookings WHERE checkIn=CAST(? AS DATE)");
stmt.setString(1, cinDate);
ResultSet results = stmt.executeQuery();
这很灵活,但根据日期格式可能无法获得您需要的确切结果(您可以查看PostgreSQL手册以获取有关日期转换格式的详细信息)。您正在使用的输入格式应该可以正常工作(例如,直接在PostgreSQL中尝试SELECT CAST('2012-05-01' AS DATE)
,这将返回正确的PostgreSQL日期。)
请注意,使用new java.sql.Date(cin.getTime())
时,您可能会遇到时区问题。您也可以使用java.sql.Date.valueOf(...)
。
在您的编辑后澄清:
这不起作用,因为日期将是SQL语法本身的一部分,而不是字符串或日期:"SELECT * FROM Rooms r where r.id not in (select * from search(" + cin +", " + cout +"))"
您至少需要使用'
引号: 。在某种程度上,您可以期望参数格式正确,但不要这样做。此外,仍然需要使用"SELECT * FROM Rooms r where r.id not in (select * from search("' + cin +"', '" + cout +"'))"
CAST('...' AS DATE)
或'...'::DATE
来投射字符串。
最简单的方法当然是:
String searchQuery = "SELECT * FROM Rooms r where r.id not in (select SOMETHING from search(CAST(? AS DATE), CAST(? AS DATE)))";
PreparedStatement ps = conn.prepareStatement(searchQuery);
ps.setString(1, cinDate);
ps.setString(2, coutDate);
(正如a_horse_with_no_name在注释中指出的那样,由于你的内部选择,一般查询无论如何都不会起作用。)
答案 1 :(得分:3)
您已经准备好有关准备好的陈述和正确格式的建议。
您还可以在很大程度上简化PostgreSQL功能:
CREATE OR REPLACE FUNCTION search(_checkin date, _checkout date)
RETURNS SETOF bookings AS
$BODY$
BEGIN
RETURN QUERY
SELECT *
FROM bookings
WHERE _checkin BETWEEN checkin AND checkout
OR _checkiut BETWEEN checkin AND checkout;
END;
$BODY$ language plpgsql;
甚至:
CREATE OR REPLACE FUNCTION search(_checkin date, _checkout date)
RETURNS SETOF bookings AS
$BODY$
SELECT *
FROM bookings
WHERE _checkin BETWEEN checkin AND checkout
OR _checkiut BETWEEN checkin AND checkout;
$BODY$ language sql;
将LOOP
加条件重写为更快的纯SQL语句。
RETURN QUERY
从 plpgsql 函数返回 - 比循环更简单,更快。这两种变体都有其优点。
答案 2 :(得分:2)