sql >> Databáze >  >> RDS >> PostgreSQL

Jaký by měl být typ parametru v Javě, když se jedná o časové razítko bez časového pásma v postgresql?

tl;dr

Pro SQL používající Half-Open span-of-time:
"SELECT * FROM tbl WHERE when !< ? AND when < ? ; "

myPreparedStatement.setObject(       // Use a prepared statement so you can pass smart objects rather than dumb strings.
    1 ,                              // Specify which placeholder is being fulfilled.
    LocalDate                        // Represent a date-only value, without time-of-day and without time zone or offset-from-UTC.
    .parse( "2014-11-20" )           // Parse an input string in standard ISO 8601 format to get a `LocalDate` object.
    .atStartOfDay()                  // Determine the first moment of the day on that date. Returns a `LocalDateTime` object representing a date with time-of-day but lacking any concept of time zone or offset-from-UTC.
) ;
myPreparedStatement.setObject( 
    2 , 
    LocalDate
    .parse( "2014-11-21" )
    .atStartOfDay()
) ;

Pozor:Hádám, že pro svůj sloupec v databázi používáte nesprávný typ. Okamžiky lze sledovat pouze pomocí TIMESTAMP WITH TIME ZONE , ne TIMESTAMP WITHOUT TIME ZONE . Pro více informací vyhledejte Stack Overflow.

Ani na okamžik

Odpověď od Jense je nyní zastaralá. V současné době byste měli používat moderní java.time třídy, které nahradily staré staré staré staré staré třídy s datem a časem.

Tento datový typ na Postgresu i standardu SQL záměrně postrádá kontext offsetu-od-UTC nebo časového pásma. Takže pozor, tento typ nemůže představovat okamžik, není bod na časové ose.

Ne, špatný datový typ. java.sql.Timestamp kromě toho, že je starší a má strašné nedostatky v designu třída představuje okamžik, konkrétní bod na časové ose. Jedná se tedy o nesoulad s vaším sloupcem typu TIMESTAMP WITHOUT TIME ZONE .

LocalDateTime

Místo toho byste měli používat LocalDateTime třída. Tato třída představuje datum s časem dne, ale postrádá jakýkoli koncept posunu nebo časového pásma.

Chcete-li získat hodnotu z databáze.

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

Chcete-li odeslat hodnotu do databáze.

myPreparedStatement.setObject( … , ldt ) ;

Začátek dne

Máte tu další nesoulad. Zadáváte pouze hodnotu data, ale váš sloupec obsahuje hodnoty data s časem dne.

Další problém:Používáte hloupé řetězce tam, kde byste měli používat inteligentní objekty. Od JDBC 4.2 si můžeme vyměňovat java.time objektů s databází. Použijte PreparedStatement se zástupnými symboly a předávat objekty přes `set

Abychom vyřešili problém data s denní dobou, musíme určit začátek dne. Pomocí LocalDateTime , nemáme žádné anomálie v časovém pásmu, které bychom museli zohlednit. Den tedy začíná vždy v 00:00. Měli bychom si však zvyknout ptát se java.time k určení začátku dne.

LocalDate startDate = LocalDate.parse( "2014-11-20" ) ;
LocalDate stopDate = LocalDate.parse( "2014-11-21" ) ;

LocalDateTime start = startDate.atStartOfDay() ;
LocalDateTime stop = stopDate.atStartOfDay() ;

Napište vám SQL se zástupnými symboly.

Navrhuji, abyste změnili své myšlení, abyste si zvykli na polootevřený přístup k definování časového rozpětí. V Half-Open je začátek včetně zatímco koncovka je výlučná . Takže pro jediný celý den 20. dne hledejte data rovnající se nebo pozdější než 20. den a dobíhající do, ale ne včetně 21. Pokud jde o první část, kratší způsob, jak říci „rovná se nebo později“, je „ne dříve“, takže používáme !< .

String sql = "SELECT * FROM tbl WHERE when !< ? AND when < ? ; " ;

Nakrmte tento sql řetězec k vašemu připravenému výpisu. Poté předejte dva LocalDateTime objektů pro zástupné symboly.

myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;


  1. Extrahujte MySQL pole řádku do PHP proměnných a pole

  2. PHP MySql (1045) Přístup odepřen pro uživatele

  3. dynamické sloupce pomocí dotazu kontingenční tabulky

  4. Mechanismus, který Oracle sleduje, když bereme horké zálohy