Bạn đang trộn double precision
đầu ra của date_part ()
với text '-'
. Điều đó không có ý nghĩa với PostgreSQL. Bạn sẽ cần truyền rõ ràng thành text
. Nhưng có một cách đơn giản hơn nhiều để thực hiện tất cả những điều này:
startdate:=date_part('year',to_timestamp(NEW.date))
||'-'||date_part('month',to_timestamp(NEW.date))
||'-'||date_part('day',to_timestamp(NEW.date));
Sử dụng thay thế:
startdate := to_char(NEW.date, 'YYYY-MM-DD');
Điều này cũng không có ý nghĩa:
EXECUTE 'CREATE TABLE $1 (
CHECK (date >= DATE $2 AND date < DATE $3 )
) INHERITS (pings)' USING quote_ident(tablename),startdate,enddate;
Bạn chỉ có thể cung cấp các giá trị bằng USING
mệnh đề. Đọc hướng dẫn tại đây . Hãy thử thay thế:
EXECUTE 'CREATE TABLE ' || quote_ident(tablename) || ' (
CHECK ("date" >= ''' || startdate || ''' AND
"date" < ''' || enddate || '''))
INHERITS (ping)';
Hoặc tốt hơn, hãy sử dụng định dạng format()
. Xem bên dưới.
Ngoài ra, giống như @a_horse đã trả lời :Bạn cần đặt các giá trị văn bản của mình trong dấu ngoặc kép.
Tương tự ở đây:
EXECUTE 'INSERT INTO $1 VALUES (NEW.*)' USING quote_ident(tablename);
Thay vào đó:
EXECUTE 'INSERT INTO ' || quote_ident(tablename) || ' VALUES ($1.*)'
USING NEW;
Câu trả lời liên quan:
Ngoài ra:Mặc dù "ngày" được cho phép đối với tên cột trong PostgreSQL, nó là từ dành riêng trong mọi tiêu chuẩn SQL . Không đặt tên cột của bạn là "ngày tháng", nó dẫn đến lỗi cú pháp khó hiểu.
Hoàn thành bản trình diễn làm việc
CREATE TABLE ping (ping_id integer, the_date date);
CREATE OR REPLACE FUNCTION trg_ping_partition()
RETURNS trigger AS
$func$
DECLARE
_tbl text := to_char(NEW.the_date, '"ping_"YYYY_DDD_') || NEW.ping_id;
BEGIN
IF NOT EXISTS (
SELECT 1
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'public' -- your schema
AND c.relname = _tbl
AND c.relkind = 'r') THEN
EXECUTE format('CREATE TABLE %I (CHECK (the_date >= %L AND
the_date < %L)) INHERITS (ping)'
, _tbl
, to_char(NEW.the_date, 'YYYY-MM-DD')
, to_char(NEW.the_date + 1, 'YYYY-MM-DD')
);
END IF;
EXECUTE 'INSERT INTO ' || quote_ident(_tbl) || ' VALUES ($1.*)'
USING NEW;
RETURN NULL;
END
$func$ LANGUAGE plpgsql SET search_path = public;
CREATE TRIGGER insbef
BEFORE INSERT ON ping
FOR EACH ROW EXECUTE PROCEDURE trg_ping_partition();
-
Cập nhật: Các phiên bản sau của Postgres có nhiều cách đơn giản hơn để kiểm tra xem bảng có tồn tại hay không:
-
to_char()
có thể lấy mộtdate
dưới dạng$1
. Nó được chuyển đổi thànhtimestamp
tự động.
Hướng dẫn sử dụng chức năng ngày / giờ . -
(Tùy chọn)
SET
search_path
cho phạm vi chức năng của bạn để tránh hành vi sai trái vớisearch_path
đã thay đổi cài đặt. -
Nhiều đơn giản hóa và cải tiến khác. So sánh mã.
Kiểm tra:
INSERT INTO ping VALUES (1, now()::date);
INSERT INTO ping VALUES (2, now()::date);
INSERT INTO ping VALUES (2, now()::date + 1);
INSERT INTO ping VALUES (2, now()::date + 1);