Có thể sử dụng CURRENT_TIMESTAMP làm KHÓA CHÍNH?


10

Có thể CURRENT_TIMESTAMPđược sử dụng như một PRIMARY KEY?

Có khả năng hai hoặc nhiều INSERT khác nhau, có giống nhau CURRENT_TIMESTAMPkhông?


3
Tôi đã nghe nói về một ứng dụng được mã hóa bằng dấu thời gian dưới dạng PK, vào những năm 1990. Mười năm sau, PC trở nên nhanh hơn và dấu thời gian được nhân đôi. Điều này gây ra những vấn đề rất nghiêm trọng, vì chức năng của ứng dụng rất quan trọng. Ngoài ra, tính duy nhất PK không được thực thi đúng trong toàn bộ ứng dụng.
Victor Di Leo

Có khả năng hai hoặc nhiều INSERT khác nhau, có cùng một CURRENT_TIMESTAMP không? Đó là đủ một truy vấn chèn 2 bản ghi cho xung đột. Vì vậy, câu trả lời cho một câu hỏi chủ đề là "KHÔNG".
Akina


3
Tôi tò mò về lý do tại sao bạn muốn điều này?
Nanne

@Nanne Tôi nghi ngờ điều này: MySQL có cách xử lý rất tốt các id số nguyên tăng tự động (đơn giản là thuộc tính auto_increment cho trường). PostgreSQL thì không, nó có một kiểu nối tiếp đẹp hơn rất nhiều.
peterh - Phục hồi Monica

Câu trả lời:


18

Theo tài liệu , độ chính xác của CURRENT_TIMESTAMPlà micro giây. Vì vậy, xác suất va chạm là thấp, nhưng có thể.

Bây giờ hãy tưởng tượng một lỗi xảy ra rất hiếm khi xảy ra và gây ra lỗi cơ sở dữ liệu. Làm thế nào là khó để gỡ lỗi nó? Đó là một lỗi nặng hơn nhiều so với một lỗi ít nhất là xác định.

Bối cảnh rộng hơn: có lẽ bạn muốn tránh những sắc thái nhỏ này với các chuỗi, điều này đặc biệt khó chịu nếu bạn đã quen với MySQL.

Hơn nữa, nếu bạn đang sử dụng các giao dịch (hầu hết các khung web, đặc biệt là các khung Java, thì làm!), Thì các dấu thời gian sẽ giống nhau trong một giao dịch! Một cuộc biểu tình:

postgres=# begin;
BEGIN
postgres=# select current_timestamp;
       current_timestamp       
-------------------------------
 2018-08-06 02:41:42.472163+02
(1 Zeile)

postgres=# select current_timestamp;
       current_timestamp       
-------------------------------
 2018-08-06 02:41:42.472163+02
(1 Zeile)

Hẹn gặp lại Hai lựa chọn, chính xác cùng một kết quả. Tôi không gõ quá nhanh. ;-)

-

Nếu bạn muốn ID dễ dàng, tránh sử dụng các chuỗi, sau đó tạo một số giá trị băm từ các định danh thực của các bản ghi. Ví dụ: nếu cơ sở dữ liệu của bạn có con người và bạn biết rằng ngày sinh của họ, tên thời con gái của mẹ và tên thật sẽ xác định duy nhất họ, sau đó sử dụng một

md5(mother_name || '-' || given_name || '-' birthday);

như id. Bên cạnh đó, bạn có thể sử dụng một CreationDatecột, sau những gì bạn lập chỉ mục cho bảng, nhưng nó không phải là một khóa (đó là id).

Ps Nói chung, đó là một cách thực hành rất tốt để làm cho DB của bạn trở nên quyết định, vì nó có thể. Tức là cùng một hoạt động sẽ tạo ra chính xác cùng một thay đổi trong DB . Bất kỳ ID dựa trên dấu thời gian nào đều thất bại tính năng quan trọng này. Điều gì nếu bạn muốn gỡ lỗi hoặc mô phỏng bất cứ điều gì? Bạn phát lại một thao tác và cùng một đối tượng sẽ được tạo bằng một id khác ... thực sự không khó để theo dõi và nó dành rất nhiều giờ làm việc.

Ps2 Bất kỳ ai kiểm tra mã của bạn trong tương lai, sẽ không có ý kiến ​​tốt nhất khi thấy các id được tạo dấu thời gian, với các lý do trên.


Ngay cả khi bạn không sử dụng giao dịch, thực tế bạn đang sử dụng các giao dịch (vì Postgres không có chế độ không giao dịch, nó chỉ có chế độ tự động). Vì vậy, nếu bạn làm một INSERTtrong nhiều hàng, tất cả chúng đều giống nhau current_timestamp. Và sau đó bạn có các kích hoạt ...
Kevin

2
Tôi đã nghe nói về một ứng dụng đã bị phá vỡ vì 2 chàng trai có cùng tên và được sinh ra cùng ngày và tên mẹ của họ giống hệt nhau. Ôi. Nếu nó CÓ THỂ xảy ra thì SILL xảy ra, sớm hay muộn.
Gunaz Balazs

@BalazsGunics Helló :-) Đó chỉ là một ví dụ. Ví dụ: trong các tình huống thực tế, tôi nghĩ id là địa chỉ email hoặc tên người dùng đã chọn (chỉ có thể được đăng ký nếu nó chưa tồn tại) là đủ. Chính phủ có xu hướng sử dụng một số số nhận dạng cá nhân, như 1 870728 0651. Điều quan trọng là, ràng buộc một id với dấu thời gian hoặc với một giá trị ngẫu nhiên là một thông lệ xấu, vì nó làm cho DB trở nên kém quyết đoán hơn.
peterh - Phục hồi Monica

@BalazsGunics Bên cạnh đó, hai người có cùng mẹ_name + give_name + sinh nhật, điều đó sẽ vẫn gây ra lỗi xác định. Xung đột khóa chính do hai giao dịch có chèn đã xảy ra trong cùng một phần triệu giây, đây vẫn là một vấn đề không xác định và rất khó có thể lặp lại.
peterh - Phục hồi Monica

10

Không thực sự bởi vì CURRENT_TIMESTAMP có thể cung cấp hai giá trị giống hệt nhau cho hai INSERT tiếp theo (hoặc một INSERT duy nhất có nhiều hàng).

Sử dụng UUID dựa trên thời gian thay thế: uuid_generate_v1mc () .


7

Nói đúng ra: Không. Bởi vì CURRENT_TIMESTAMPlà một hàm và chỉ một hoặc nhiều cột trong bảng có thể tạo thành một PRIMARY KEYràng buộc.

Nếu bạn muốn tạo một PRIMARY KEYràng buộc trên một cột có giá trị mặc định CURRENT_TIMESTAMP, thì câu trả lời là: Có, bạn có thể . Không có gì ngăn cản bạn làm điều đó, giống như không có gì ngăn bạn bắn táo từ đầu con trai bạn. Câu hỏi vẫn không có ý nghĩa trong khi bạn không xác định mục đích của nó. Những loại dữ liệu nào là cột và bảng được cho là giữ? Những quy tắc bạn đang cố gắng để thực hiện?

Thông thường, ý tưởng bị ràng buộc để chạy vào các lỗi khóa trùng lặp do CURRENT_TIMESTAMPmột STABLEhàm trả về cùng một giá trị cho cùng một giao dịch (thời gian bắt đầu của giao dịch). Nhiều INSERT trong cùng một giao dịch bị ràng buộc để va chạm - giống như các câu trả lời khác đã được minh họa. Hướng dẫn sử dụng:

Vì các hàm này trả về thời gian bắt đầu của giao dịch hiện tại, giá trị của chúng không thay đổi trong quá trình giao dịch. Đây được coi là một tính năng: mục đích là cho phép một giao dịch duy nhất có một khái niệm nhất quán về thời gian hiện tại, vì vậy nhiều sửa đổi trong cùng một giao dịch có cùng dấu thời gian.

Dấu thời gian của Postgres được triển khai dưới dạng số nguyên 8 byte đại diện cho tối đa 6 chữ số phân số (độ phân giải micro giây).

Nếu bạn đang xây dựng một bảng được cho là giữ không quá một hàng mỗi micro giây và điều kiện đó sẽ không thay đổi (một cái gì đó được đặt tên sensor_reading_per_microsecond), thì nó có thể có ý nghĩa. Các hàng trùng lặp được cho là gây ra lỗi vi phạm khóa trùng lặp. Đó là một ngoại lệ kỳ lạ, mặc dù. Và kiểu dữ liệu timestamptz(không timestamp) có lẽ sẽ thích hợp hơn. Xem:

Thay vào đó, tôi vẫn muốn sử dụng khóa chính nối tiếp thay thế. Và thêm một UNIQUEràng buộc trên cột dấu thời gian. Ít biến chứng có thể xảy ra hơn, không dựa vào chi tiết triển khai của RDBMS.


Thậm chí sensor_reading_per_microsecondcó thể va chạm nếu bạn hoàn toàn không thể đảm bảo rằng thời gian của mỗi lần đọc được đồng bộ hóa hoàn hảo so với lần đọc trước; một độ lệch dưới micro giây (thường không phải là không thể) phá vỡ lược đồ. Nói chung tôi vẫn hoàn toàn tránh điều này. (Xin lưu ý bạn, như bạn đã chỉ ra, trong trường hợp như vậy, kết quả va chạm có thể là mong muốn!)
Các cuộc đua nhẹ nhàng trong quỹ đạo

@ Lightness: Tôi hoàn toàn đồng ý. Ví dụ của bạn với sự thay đổi thời gian ngoài ý muốn sau một sai lệch tròn nhỏ minh họa cho một cảnh báo khác.
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.