sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvad skal typen af ​​parameter være i Java, når det er et tidsstempel uden tidszone i postgresql?

tl;dr

For SQL, der bruger Half-Open tidsrum:
"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()
) ;

Pas på:Jeg gætter på, at du bruger den forkerte type til din kolonne i din database. Øjeblikke kan kun spores med TIMESTAMP WITH TIME ZONE , ikke TIMESTAMP WITHOUT TIME ZONE . Søg efter Stack Overflow for at få flere oplysninger.

Ikke et øjeblik

Svaret af Jens er nu forældet. I dag bør du bruge den moderne java.time klasser, der fortrængte de besværlige gamle gamle dato-tidsklasser.

Denne datatype på både Postgres og SQL-standarden mangler bevidst konteksten af ​​en offset-fra-UTC eller en tidszone. Så pas på, denne type kan ikke repræsentere et øjeblik, er ikke et punkt på tidslinjen.

Nej, forkert datatype. Udover at være arv og være frygtelig mangelfuld i designet, er java.sql.Timestamp klasse repræsenterer et øjeblik, et bestemt punkt på tidslinjen. Så dette er en uoverensstemmelse med din kolonne af typen TIMESTAMP WITHOUT TIME ZONE .

LocalDateTime

Du bør i stedet bruge LocalDateTime klasse. Denne klasse repræsenterer en dato med et klokkeslæt, men mangler noget begreb om forskydning eller tidszone.

For at hente en værdi fra databasen.

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

For at sende en værdi til databasen.

myPreparedStatement.setObject( … , ldt ) ;

Start på dagen

Du har endnu et misforhold her. Du angiver en kun datoværdi, men din kolonne indeholder dato-med-klokkeslæt-værdier.

Et andet problem:Du bruger dumme strenge, hvor du burde bruge smarte objekter. Fra JDBC 4.2 kan vi udveksle java.time objekter med databasen. Brug en PreparedStatement med pladsholdere, og send objekter via `sættet

For at løse datoen med klokkeslætsproblemet skal vi bestemme starten på dagen. Med LocalDateTime , vi har ingen tidszone-anomalier at tage højde for. Så dagen starter altid kl 00:00. Ikke desto mindre bør vi vænne os til at spørge java.time for at bestemme starten på dagen.

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

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

Skriv din SQL med pladsholdere.

Jeg foreslår, at du ændrer din tankegang for at gøre en vane med den halvåbne tilgang til at definere tidsrum. I Half-Open er begyndelsen inklusive mens slutningen er eksklusiv . Så for den enkelte dag i den 20. skal du søge efter datoer, der er lig med eller senere end den 20. og løber op til, men ikke inklusive den 21. Hvad angår den første del, er en kortere måde at sige "lig med eller senere" "ikke før", så vi bruger !< .

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

Feed den sql streng til din forberedte erklæring. Send derefter de to LocalDateTime objekter til pladsholderne.

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


  1. ændre tabel tilføje ... før `kode`?

  2. kan ikke oprette forbindelse til serveren for Postgres

  3. SQL Server-forespørgsels-xml-attribut for en elementværdi

  4. SQL PLUS Trigger kompileringsfejl