Trước hết, tôi sẽ không thêm một cột truy cập vào bảng Main
. Tôi sẽ tạo một bảng Audit
riêng biệt có thể giữ ID
mục từ bảng Main
cộng với ít nhất dấu thời gian khi yêu cầu ID
đó. Về bản chất, bảng Audit
sẽ lưu trữ lịch sử yêu cầu. Trong phương pháp này, bạn có thể dễ dàng tạo ra nhiều báo cáo thú vị hơn. Bạn luôn luôn có thể tính toán tổng số lớn cho mỗi mục và bạn cũng có thể tính toán tóm tắt theo ngày, tuần, tháng, vv cho mỗi mục hoặc trên tất cả các mục. Tùy thuộc vào khối lượng dữ liệu bạn có thể xóa các mục kiểm tra định kỳ cũ hơn một số ngưỡng (một tháng, một năm, v.v ...).
Ngoài ra, bạn có thể dễ dàng lưu trữ thêm thông tin trong bảng Audit
nếu cần, ví dụ: ID người dùng để tính số liệu thống kê cho mỗi người dùng.
Để điền Audit
bảng "tự động", tôi sẽ tạo một quy trình được lưu trữ. Mã máy khách sẽ gọi thủ tục lưu sẵn này thay vì thực hiện SELECT
gốc. Thủ tục được lưu trữ sẽ trả về chính xác kết quả tương tự như mã gốc SELECT
, nhưng cũng sẽ thêm các chi tiết cần thiết vào bảng Audit
một cách minh bạch vào mã máy khách.
Vì vậy, chúng ta hãy giả sử rằng Audit
bảng trông như thế này:
CREATE TABLE AuditTable
(
ID int
IDENTITY -- SQL Server
SERIAL -- Postgres
AUTO_INCREMENT -- MySQL
NOT NULL,
ItemID int NOT NULL,
RequestDateTime datetime NOT NULL
)
và chính bạn SELECT
trông như thế này:
SELECT ItemID, Col1, Col2, ...
FROM MainTable
WHERE <complex criteria>
Thực hiện cả hai INSERT
và SELECT
trong một tuyên bố trong SQL Server tôi 'd sử dụng mệnh đề OUTPUT
, trong mệnh đề Postgres - RETURNING
, trong MySQL - ??? Tôi không nghĩ rằng nó có bất cứ điều gì như thế này. Vì vậy, thủ tục MySQL sẽ có một số câu lệnh riêng biệt.
MySQL
Lúc đầu làm SELECT
của bạn và chèn kết quả vào một temporary (có thể nhớ) bảng. Sau đó sao chép ID mục từ bảng tạm thời vào bảng Audit
. Sau đó, SELECT
từ bảng tạm thời để trả lại kết quả cho khách hàng.
CREATE TEMPORARY TABLE TempTable
(
ItemID int NOT NULL,
Col1 ...,
Col2 ...,
...
)
ENGINE = MEMORY
SELECT ItemID, Col1, Col2, ...
FROM MainTable
WHERE <complex criteria>
;
INSERT INTO AuditTable (ItemID, RequestDateTime)
SELECT ItemID, NOW()
FROM TempTable;
SELECT ItemID, Col1, Col2, ...
FROM TempTable
ORDER BY ...;
SQL Server (chỉ để trêu chọc bạn. Câu lệnh này hiện cả hai INSERT
và SELECT
)
MERGE INTO AuditTable
USING
(
SELECT ItemID, Col1, Col2, ...
FROM MainTable
WHERE <complex criteria>
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ItemID, RequestDateTime)
VALUES
(Src.ItemID, GETDATE())
OUTPUT
Src.ItemID, Src.Col1, Src.Col2, ...
;
Bạn có thể để lại Audit
bảng như nó có, hoặc bạn có thể thiết lập cron để tóm tắt nó định kỳ. Nó thực sự phụ thuộc vào khối lượng dữ liệu. Trong hệ thống của chúng tôi, chúng tôi lưu trữ các hàng riêng lẻ trong một tuần, cộng với chúng tôi tóm tắt số liệu thống kê mỗi giờ và giữ nó trong 6 tuần, cộng với chúng tôi giữ bản tóm tắt hàng ngày trong 18 tháng. Nhưng, phần quan trọng, tất cả các tóm tắt này là các bảng riêng biệt, chúng tôi không giữ thông tin kiểm tra trong bảng Main
, vì vậy chúng tôi không cần phải cập nhật nó.
Joe Celko giải thích nó rất tốt trong SQL Style Habits: Attack of the Skeuomorphs:
Bây giờ đi đến bất kỳ văn bản SQL diễn đàn tìm kiếm các thông tin đăng. Bạn sẽ tìm thấy hàng nghìn bài đăng có DDL bao gồm các cột có tên là createdby
, createddate
, modifiedby
và modifieddate
với dữ liệu meta cụ thể đó ở cuối hàng. Đây là nhãn băng cũ được viết bằng ngôn ngữ mới! Deja Vu!
Bản ghi tiêu đề chỉ xuất hiện một lần trên băng. Nhưng các giá trị dữ liệu meta này xuất hiện lặp đi lặp lại trên mỗi hàng trong bảng. Một trong những lý do chính của để sử dụng cơ sở dữ liệu (không chỉ SQL) là loại bỏ dự phòng khỏi dữ liệu; điều này chỉ làm tăng thêm sự thừa. Nhưng bây giờ hãy suy nghĩ về điều gì xảy ra với đường mòn kiểm toán khi một hàng bị xóa? Điều gì sẽ xảy ra với đường mòn kiểm tra khi một hàng được cập nhật? Đường mòn bị phá hủy. Dữ liệu kiểm tra phải được tách riêng khỏi lược đồ. Bạn có đặt tệp nhật ký trên cùng một ổ đĩa làm cơ sở dữ liệu không? Kế toán viên có cho phép cùng một người chấp nhận và nhận thanh toán không?
INSERT INTO mytable (col1, col2, col3 ...) CHỌN col1, col2, col3 TỪ anotherTable – bksi
Liệu truy vấn đó sẽ trả về tất cả các cột từ câu lệnh SELECT cuối cùng?Tôi muốn chỉ chèn cột ID vào bảng khác, và sau đó quay trở lại PHP tất cả các cột khác của cùng một câu lệnh SELECT. Đó có phải là cách INSERT INTO hoạt động không? – Ecksters
Không thể với MySQL. Bạn sẽ phải sử dụng hai truy vấn. – rjdown