PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cắt tỉa phân vùng dựa trên ràng buộc kiểm tra không hoạt động như mong đợi

Cột của bạn created_attimestamp without time zone .

Nhưng now() trả về timestamp with time zone . Biểu thức now() - '1 hour'::interval đang bị ép buộc vào timestamp [without time zone] , mang theo hai vấn đề :

1.) Bạn đã không yêu cầu điều này, nhưng biểu hiện là không đáng tin cậy. Kết quả của nó phụ thuộc vào cài đặt múi giờ hiện tại của phiên truy vấn đang được thực thi. Chi tiết tại đây:

Để làm cho biểu thức rõ ràng, bạn có thể sử dụng:

now() AT TIME ZONE 'Europe/London' -- your time zone here

Hoặc chỉ cần (đọc hướng dẫn tại đây) :

LOCALTIMESTAMP  -- explicitly take the local time

Tôi sẽ cân nhắc làm việc với timestamptz thay vào đó.
Không giải quyết được vấn đề thứ hai của bạn:

2.) Câu trả lời cho câu hỏi của bạn. Loại trừ ràng buộc không hoạt động. Theo tài liệu:

Nhấn mạnh đậm của tôi.

now() là triển khai Postgres của CURRENT_TIMESTAMP . Như bạn có thể thấy trong danh mục hệ thống, nó chỉ là STABLE , không phải IMMUTABLE :

SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';

proname | provolatile
--------+------------
now     | s              -- meaning: STABLE

Giải pháp

1.) Bạn có thể khắc phục hạn chế bằng cách cung cấp một hằng số trong WHERE điều kiện (luôn là "không thay đổi"):

select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp;  -- derived from your example

2.) Hoặc bằng cách "giả mạo" một hàm bất biến:

CREATE FUNCTION f_now_immutable()
  RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC'  -- your time zone here
$func$  LANGUAGE sql IMMUTABLE;

Và sau đó:

select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'

Hãy cẩn thận với cách bạn sử dụng điều này mặc dù:while now()STABLE (không thay đổi trong suốt thời gian giao dịch), nó không thay đổi giữa các giao dịch, vì vậy hãy cẩn thận không sử dụng điều này trong các câu lệnh đã chuẩn bị sẵn (ngoại trừ dưới dạng giá trị tham số) hoặc chỉ mục hoặc bất kỳ thứ gì mà nó có thể cắn bạn.

3.) Hoặc bạn có thể thêm hằng số dường như dư thừa WHERE mệnh đề cho truy vấn hiện tại của bạn phù hợp với ràng buộc trên phân vùng của bạn:

SELECT count(*)
FROM   events
WHERE  created_at > now() - '1 hour'::interval
AND    created_at >= '2015-04-01 00:00:00'::timestamp
AND    created_at <= '2015-04-30 23:59:59.999999'::timestamp;

Chỉ cần đảm bảo rằng now() - '1 hour'::interval rơi vào đúng phân vùng hoặc bạn không nhận được kết quả rõ ràng.

Ngoài ra:Tôi muốn sử dụng biểu thức này trong CHECK ràng buộc và truy vấn. Dễ dàng xử lý hơn và thực hiện tương tự:

       created_at >= '2015-04-01 0:0'::timestamp
AND    created_at <  '2015-05-01 0:0'::timestamp



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tổng hợp kết nối Postgres - nhiều người dùng

  2. PostgreSQL 13:GIỚI HẠN… CÓ TIES

  3. Lợi ích của PostgreSQL

  4. SQL - Cách thoát dấu ngoặc đơn trong PostgreSQL

  5. Tham gia với hàm trả về thiết lập (SRF) và truy cập các cột trong SQLAlchemy