2009-02-17 48 views
5

Có cách nào đặc biệt để khai báo cột DateCreated trong bảng MS Sql Server sao cho nó sẽ tự động điền nó với dấu thời gian thích hợp khi được tạo?DateCreated cột trong Sql Server?

Hoặc .. tôi có phải cung cấp datetime cho nó khi tôi thực hiện truy vấn, theo cách thủ công không?

Trả lời

10

Bạn có thể đặt giá trị mặc định của cột thành "getdate()"

+1

Hãy lưu ý rằng người dùng có thể bỏ qua vì giá trị mặc định không được tính đến khi bạn chèn giá trị thực. Và nó cũng có thể được cập nhật bởi người dùng. Nó có thể đủ tốt nếu bạn có thể kiểm soát những gì SQL được chạy (và bạn không thể :-) nhưng nó không an toàn. – paxdiablo

+0

Đó thực sự là một điều tốt bởi vì nếu người dùng có một ngày cụ thể họ cần phải đặt ở đó, có lẽ nó nên được cho phép trừ khi bạn có các quy tắc chi phối khác. – James

+0

Tôn trọng không đồng ý, @James. Bạn chưa từng nghe về Sarbanes-Oxley chưa? :-) Nếu bạn có cột DateCreated, nó sẽ được đặt thành ngày hàng được tạo. Nếu bạn muốn một cột có thể thay đổi người dùng, nó sẽ được gọi là DateCreatedForPurposesOfFraud hoặc một cái gì đó tương tự. – paxdiablo

15

Giá trị mặc định bị hai hạn chế lớn.

  • nếu câu lệnh chèn chỉ định giá trị cho cột, mặc định không được sử dụng.
  • cột có thể được cập nhật bất kỳ lúc nào.

Điều này có nghĩa là bạn không thể chắc chắn rằng các giá trị chưa được sửa đổi ngoài tầm kiểm soát của bạn.

Nếu bạn muốn tính toàn vẹn dữ liệu thực sự (để bạn chắc chắn ngày trong hàng là ngày tạo), bạn cần sử dụng trình kích hoạt.

Trình kích hoạt chèn để đặt cột cho ngày hiện tại và trình kích hoạt cập nhật để ngăn thay đổi cho cột đó (hoặc chính xác hơn, đặt giá trị hiện tại) là cách để triển khai cột DateCreated.

Trình kích hoạt chèn và cập nhật để đặt cột cho ngày hiện tại là cách triển khai cột DateModified.

(chỉnh sửa từ người dùng Gabriel - đây là nỗ lực của tôi để thực hiện điều này như mô tả - Tôi không chắc chắn 100% đó là đúng nhưng tôi hy vọng OP đánh giá nó ...):

CREATE TRIGGER [dbo].[tr_Affiliate_IU] 
    ON [dbo].[Affiliate] 
    AFTER INSERT, UPDATE 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Get the current date. 
    DECLARE @getDate DATETIME = GETDATE() 

    -- Set the initial values of date_created and date_modified. 
    UPDATE 
     dbo.Affiliate 
    SET 
     date_created = @getDate 
    FROM 
     dbo.Affiliate A 
     INNER JOIN INSERTED I ON A.id = I.id 
     LEFT OUTER JOIN DELETED D ON I.id = D.id 
    WHERE 
     D.id IS NULL 

    -- Ensure the value of date_created does never changes. 
    -- Update the value of date_modified to the current date. 
    UPDATE 
     dbo.Affiliate 
    SET 
     date_created = D.date_created 
     ,date_modified = @getDate 
    FROM 
     dbo.Affiliate A 
     INNER JOIN INSERTED I ON A.id = I.id 
     INNER JOIN DELETED D ON I.id = D.id 
END 
+0

Nếu bạn kiểm soát môi trường và ứng dụng thì bạn kiểm soát quyền truy cập vào tầng dữ liệu. Hai mối quan tâm sau đó trở nên không liên quan. –

+0

Thực sự, bạn không nghĩ rằng ai đó chỉ có thể kết nối với DBMS bằng trình điều khiển JDBC? Và một trong những ưu điểm chính của n-tier là có từng cấp chịu trách nhiệm về tính toàn vẹn của chính nó. Bạn KHÔNG BAO GIỜ cho rằng DB được bảo vệ bởi ứng dụng khi nó có thể bảo vệ chính nó. Đó là yêu cầu cho sự cố. – paxdiablo

+0

@Pax: Không, tôi không. Một kết nối ad-hoc không thể kết nối với một môi trường được bảo mật thích hợp. An ninh không phải là trách nhiệm duy nhất của DMBS (nó cung cấp một điểm khởi đầu) vì nó phải là một chiến lược rộng lớn. –

0

Chắc chắn là.

Dưới đây là ví dụ đang hoạt động cho bạn.

Create table #TableName 
(
    ID INT IDENTITY(1,1) PRIMARY KEY, 
    CreatedDate DATETIME NOT NULL DEFAULT GETDATE(), 
    SomeDate VARCHAR(100) 
) 

INSERT INTO #TableName (SomeDate) 
SELECT 'Some data one' UNION ALL SELECT 'some data two' 

SELECT * FROM #TableName 

DROP TABLE #TableName 
+0

Và những gì sẽ xảy ra khi một nhân viên bất mãn đến cùng với "UPDATE #TABLE SET CREATEDDATE = GETDATE()"? Bang, có tất cả các thông tin có giá trị của bạn khi các hàng được tạo ra. – paxdiablo

+2

@Pax: Tuy nhiên, sẽ không xảy ra trên sân của tôi, trong trường hợp không chắc chắn, tôi sẽ chỉ thực hiện các thủ tục DR của chúng tôi và khôi phục dữ liệu. Âm thanh như bạn cần nhìn vào chiến lược bảo mật và tinh thần nhân viên của bạn :-) –

+1

"Tinh thần", nhưng có lẽ đạo đức của họ cũng nên được kiểm tra :-) Dù sao, phòng ngừa luôn tốt hơn phục hồi. Đó là sự khác biệt giữa không có thời gian chết và một số thời gian chết (không ai là tốt hơn so với bất kỳ số tiền). Nó có lẽ là môi trường tôi làm việc nhiều hơn, DB2 trên Hệ thống z, chúng ta luôn luôn hoang tưởng. – paxdiablo

2

Chúng tôi có DEFAULT trên CreatedDate và không thực thi với Triggers

Có những lúc chúng ta muốn thiết lập ngày tháng rõ ràng - ví dụ nếu chúng tôi nhập dữ liệu từ một số nguồn khác.

Có một rủi ro mà Bug Ứng dụng có thể gây rối với các Tạo ngày, hoặc một DBA bất mãn cho rằng vấn đề (chúng tôi không có phi DBA kết nối trực tiếp đến DBS của chúng tôi)

Tôi cho rằng bạn có thể đặt Column- cấp quyền trên CreateDate.

Nhà nửa đường có thể là để INSERT TRIGGER tạo hàng trong bảng 1: 1, do đó cột đó nằm ngoài bảng chính. Bảng thứ hai có thể có quyền SELECT, trong đó bảng chính có quyền UPDATE và do đó không cần trình kích hoạt UPDATE để ngăn các thay đổi đối với CreateDate - điều này sẽ loại bỏ một số "trọng lượng" khi cập nhật các hàng bình thường.

Tôi cho rằng bạn coul có một UPDATE/DELETE kích hoạt trên bảng thứ hai để ngăn chặn sự thay đổi (mà sẽ không bao giờ được thực hiện trong trường hợp bình thường, vì vậy "nhẹ")

Bit của một nỗi đau để có bảng phụ mặc dù ... có thể có một bảng cho tất cả các CreateDates - TableName, PK, CreateDate.Hầu hết các kiến ​​trúc sư cơ sở dữ liệu sẽ ghét điều đó mặc dù ...

Các vấn đề liên quan