올바른 값을 제공하더라도 데이터베이스가 항상 기본값을 확인한다고 가정하므로 동일한 작업을 두 번 수행합니다.
음, 왜 그렇게 생각하십니까? ;-). 연결된 열이 INSERT
명령문에 존재하지 않을 때 기본값을 제공하여 값을 제공한다는 점을 감안할 때 , 연관된 열이 INSERT
명령문 에 있으면 완전히 무시된다고 가정합니다 .
다행스럽게도 우리 중 어느 누구도 문제 의이 진술로 인해 아무것도 가정 할 필요가 없습니다.
나는 주로 성능에 관심이 있습니다.
성능에 대한 질문은 거의 항상 테스트 할 수 있습니다. 따라서 SQL Server (여기의 실제 권한)가이 질문에 대답 할 수 있도록 테스트를해야합니다.
설정
다음을 한 번 실행하십시오.
SET NOCOUNT ON;
-- DROP TABLE #HasDefault;
CREATE TABLE #HasDefault
(
[HasDefaultID] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[SomeInt] INT NULL,
[SomeDate] DATETIME NOT NULL DEFAULT (GETDATE())
);
-- DROP TABLE #NoDefault;
CREATE TABLE #NoDefault
(
[NoDefaultID] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[SomeInt] INT NULL,
[SomeDate] DATETIME NOT NULL
);
-- make sure that data file and Tran Log file are grown, if need be, ahead of time:
INSERT INTO #HasDefault ([SomeInt])
SELECT TOP (2000000) NULL
FROM [master].sys.[all_columns] ac1
CROSS JOIN [master].sys.[all_columns] ac2;
타이밍 1을 기울이기 때문에 테스트 1A와 1B를 개별적으로 실행하십시오. 각각에 대한 평균 타이밍을 파악하려면 각각을 여러 번 실행하십시오.
테스트 1A
TRUNCATE TABLE #HasDefault;
GO
PRINT '#HasDefault:';
SET STATISTICS TIME ON;
INSERT INTO #HasDefault ([SomeDate])
SELECT TOP (1000000) '2017-05-15 10:11:12.000'
FROM [master].sys.[all_columns] ac1
CROSS JOIN [master].sys.[all_columns] ac2;
SET STATISTICS TIME OFF;
GO
테스트 1B
TRUNCATE TABLE #NoDefault;
GO
PRINT '#NoDefault:';
SET STATISTICS TIME ON;
INSERT INTO #NoDefault ([SomeDate])
SELECT TOP (1000000) '2017-05-15 10:11:12.000'
FROM [master].sys.[all_columns] ac1
CROSS JOIN [master].sys.[all_columns] ac2;
SET STATISTICS TIME OFF;
GO
타이밍이 왜곡되므로 테스트 2A 및 2B를 개별적으로 실행하십시오. 각각에 대한 평균 타이밍을 파악하려면 각각을 여러 번 실행하십시오.
테스트 2A
TRUNCATE TABLE #HasDefault;
GO
DECLARE @Counter INT = 0,
@StartTime DATETIME,
@EndTime DATETIME;
BEGIN TRAN;
--SET STATISTICS TIME ON;
SET @StartTime = GETDATE();
WHILE (@Counter < 100000)
BEGIN
INSERT INTO #HasDefault ([SomeDate]) VALUES ('2017-05-15 10:11:12.000');
SET @Counter = @Counter + 1;
END;
SET @EndTime = GETDATE();
--SET STATISTICS TIME OFF;
COMMIT TRAN;
PRINT DATEDIFF(MILLISECOND, @StartTime, @EndTime);
테스트 2B
TRUNCATE TABLE #NoDefault;
GO
DECLARE @Counter INT = 0,
@StartTime DATETIME,
@EndTime DATETIME;
BEGIN TRAN;
--SET STATISTICS TIME ON;
SET @StartTime = GETDATE();
WHILE (@Counter < 100000)
BEGIN
INSERT INTO #NoDefault ([SomeDate]) VALUES ('2017-05-15 10:11:12.000');
SET @Counter = @Counter + 1;
END;
SET @EndTime = GETDATE();
--SET STATISTICS TIME OFF;
COMMIT TRAN;
PRINT DATEDIFF(MILLISECOND, @StartTime, @EndTime);
테스트 1A와 1B 사이 또는 테스트 2A와 2B 사이의 타이밍에는 실제 차이가 없음을 알아야합니다. 따라서, DEFAULT
정의되었지만 사용 하지 않은 성능에 대한 불이익은 없습니다 .
또한 의도 된 동작을 문서화하는 것 외에도 저장 프로 시저에 완전히 포함 된 DML 문에 관심이있는 사람은 대부분 사용자임을 명심해야합니다. 지원 담당자는 신경 쓰지 않습니다. 미래의 개발자는 모든 DML을 이러한 저장 프로 시저 내에 캡슐화하거나 알고있는 경우에도 관리하려는 사용자의 요구를 인식하지 못할 수 있습니다. 그리고 당신이 사라진 후에 (다른 프로젝트 나 직업)이 DB를 유지하는 사람은 아무리 항의하더라도 ORM의 사용을 신경 쓰지 않거나 막지 못할 수도 있습니다. 따라서 Defaults 는 지원 담당자가 수행 할 때 INSERT
특별 INSERT
하게 수행 할 때 사람들에게 "아웃"을 제공하는 데 도움이 될 수 있습니다. 날짜 열).
그리고, DEFAULT
관련 열이 INSERT
명령문에 존재할 때 a 가 검사 되는지 여부를 다소 객관적으로 표시 할 수 있다는 것이 나에게 발생했습니다 . 유효하지 않은 값을 제공하십시오. 다음과 같은 테스트 만 수행됩니다.
-- DROP TABLE #BadDefault;
CREATE TABLE #BadDefault
(
[BadDefaultID] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[SomeInt] INT NOT NULL DEFAULT (1 / 0)
);
INSERT INTO #BadDefault ([SomeInt]) VALUES (1234); -- Success!!!
SELECT * FROM #BadDefault; -- just to be sure ;-)
INSERT INTO #BadDefault ([SomeInt]) VALUES (DEFAULT); -- Error:
/*
Msg 8134, Level 16, State 1, Line xxxxx
Divide by zero error encountered.
The statement has been terminated.
*/
SELECT * FROM #BadDefault; -- just to be sure ;-)
GO
보시다시피, 열 (및 키워드 DEFAULT
가 아닌 값 )이 제공되면 기본값은 100 % 무시됩니다. 우리는 INSERT
성공 하기 때문에 이것을 알고 있습니다. 그러나 Default가 사용되면 최종적으로 실행될 때 오류가 발생합니다.
트리거 실행 내에서 DEFAULT 제약 조건을 피할 수있는 방법이 있습니까?
(이 문맥에서 적어도) 초기 구속을 피하기 위해 필요하지만 완전성을 위하여는 단지 "를 방지의"내 기본 구속 할 수있을 것이라는 점을 알 수있다 완전히 불필요 INSTEAD OF
하지만, 트리거 되지 내의 AFTER
트리거. CREATE TRIGGER 의 문서에 따르면 :
트리거 테이블에 제한 조건이 존재하면 INSTEAD OF 트리거 실행 후 및 AFTER 트리거 실행 전에 제한 조건이 점검됩니다. 제한 조건을 위반하면 INSTEAD OF 트리거 조치가 롤백되고 AFTER 트리거가 실행되지 않습니다.
물론 INSTEAD OF
트리거를 사용 하려면 다음이 필요합니다.
- 기본 구속 조건 비활성화
AFTER
구속 조건을 활성화 하는 트리거 생성
그러나 나는 이것을하는 것을 권장하지 않습니다.