Postgresql的格式化日期

时间:2012-05-05 11:50:43

标签: java postgresql date

我有以下

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不会读取它

3 个答案:

答案 0 :(得分:3)

听起来你通过将它们直接连接到字符串来传递参数。这是一个非常糟糕的主意,因为它可能导致SQL注入。永远use PreparedStatements?占位符一起传递参数,永远不要直接将它们直接连接到查询字符串中(更多的是,你需要'分隔符)。

你可以拥有类似的东西:

 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 函数返回 - 比循环更简单,更快。
  • 或使用简单的 sql 功能。

这两种变体都有其优点。

答案 2 :(得分:2)

根据this page,SQL中日期/时间字符串的标准格式为:

YYYY-MM-DD HH:MM:SS

当然,对于日期,您可以使用

YYYY-MM-DD

PostgreSQL接受其他格式(有关详细信息,请参阅here),但没有理由不遵守标准。

然而,因为您收到语法错误,听起来好像是在没有正确引用/转义的情况下将日期字符串注入到SQL语句中。仔细检查您是否正确地转移了输入。