$$
hanyalah minimum untuk mengutip dolar
. Buat (jauh!) lebih kecil kemungkinannya untuk berkonflik dengan string dalam literal terlampir dengan meletakkan string di antara dolar:
CREATE OR REPLACE FUNCTION time_to_sec(timepoint timestamp with time zone)
RETURNS bigint LANGUAGE plpgsql AS
$BODY$
DECLARE
seconds bigint;
secondsFromEpoch bigint;
secondsFromMidnight bigint;
BEGIN
secondsFromEpoch = EXTRACT(EPOCH FROM timepoint)::bigint;
secondsFromMidnight = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP::date)::bigint;
seconds = secondsFromEpoch - secondsFromMidnight;
return seconds;
END;
$BODY$;
Saran lebih lanjut
-
Operator penugasan di plpgsql adalah
:=
.=
tidak didokumentasikan dan mungkin hilang di rilis mendatang. Selengkapnya di bawah pertanyaan terkait ini . -
Gunakan
CURRENT_DATE
bukannyaCURRENT_TIMESTAMP::date
. -
Itu diperbolehkan, tetapi saya menyarankan untuk tidak menggunakan nama parameter kasus campuran di plpgsql. Mereka tidak peka huruf besar/kecil.
-
Yang terpenting, sederhanakan :
CREATE OR REPLACE FUNCTION time_to_sec2(timepoint timestamp with time zone) RETURNS bigint LANGUAGE plpgsql STABLE AS $BODY$ BEGIN RETURN EXTRACT(EPOCH FROM timepoint - current_date)::bigint; END; $BODY$;
Atau bahkan:
CREATE OR REPLACE FUNCTION time_to_sec3(timepoint timestamp with time zone) RETURNS bigint LANGUAGE sql AS $BODY$ SELECT EXTRACT(EPOCH FROM timepoint - current_date)::bigint; $BODY$;
-
Dapat dideklarasikan
STABLE
!
- Ada juga fungsi yang terkait erat
age()
di PostgreSQL melakukan hampir, tetapi tidak cukup, sama:ia mengembalikan hasil "simbolis" dengan tahun dan bulan standar. Oleh karena itu, ekspresikan denganage()
dapat memberikan hasil yang berbeda untuk jangka waktu yang lebih lama.
Ini semua setara - kecuali untuk dua yang terakhir menyimpang dengan periode waktu yang lebih lama:
WITH x(t) AS (VALUES ('2012-07-20 03:51:26+02'::timestamptz))
SELECT time_to_sec(t) AS t1
,time_to_sec2(t) AS t2
,time_to_sec3(t) AS t3
,EXTRACT(EPOCH FROM t - current_date)::bigint AS t4
,EXTRACT(EPOCH FROM age(t, current_date))::bigint AS t5 -- deviates
,EXTRACT(EPOCH FROM age(t))::bigint * -1 AS t6 -- deviates
FROM x;
Mengenai pertanyaan awal:pesan kesalahan PostgreSQL ini tidak berarti masalahnya ada pada tanda dolar:
Sebagian besar waktu itu adalah ;
. yang hilang sebelum garis itu. Atau mungkin karakter khusus yang tidak lolos dalam XML, seperti < > &
? Tanda dolar $
harus baik-baik saja. Tapi saya tidak ahli dengan semut. Seharusnya ada lebih banyak konteks di log PostgreSQL.