TSQL 변수를 상수로 만드는 방법이 있습니까?
TSQL 변수를 상수로 만드는 방법이 있습니까?
답변:
아니요,하지만 함수를 생성하고 거기에 하드 코딩하여 사용할 수 있습니다.
다음은 그 예입니다.
CREATE FUNCTION fnConstant()
RETURNS INT
AS
BEGIN
RETURN 2
END
GO
SELECT dbo.fnConstant()
WITH SCHEMABINDING
에서 사용 CREATE FUNCTION
하는 것입니다. 맞습니까?
Jared Ko가 제공하는 한 가지 해결책은 pseudo-constants 를 사용하는 것 입니다.
SQL Server에 설명 된대로 : 변수, 매개 변수 또는 리터럴? 아니면 ... 상수? :
의사 상수는 변수 나 매개 변수가 아닙니다. 대신 단순히 하나의 행과 상수를 지원하기에 충분한 열이있는보기입니다. 이러한 간단한 규칙을 사용하면 SQL 엔진은 뷰의 값을 완전히 무시하지만 여전히 해당 값에 따라 실행 계획을 작성합니다. 실행 계획은 뷰에 대한 조인도 표시하지 않습니다!
다음과 같이 작성하십시오.
CREATE SCHEMA ShipMethod GO -- Each view can only have one row. -- Create one column for each desired constant. -- Each column is restricted to a single value. CREATE VIEW ShipMethod.ShipMethodID AS SELECT CAST(1 AS INT) AS [XRQ - TRUCK GROUND] ,CAST(2 AS INT) AS [ZY - EXPRESS] ,CAST(3 AS INT) AS [OVERSEAS - DELUXE] ,CAST(4 AS INT) AS [OVERNIGHT J-FAST] ,CAST(5 AS INT) AS [CARGO TRANSPORT 5]
그런 다음 다음과 같이 사용하십시오.
SELECT h.* FROM Sales.SalesOrderHeader h JOIN ShipMethod.ShipMethodID const ON h.ShipMethodID = const.[OVERNIGHT J-FAST]
또는 다음과 같이 :
SELECT h.* FROM Sales.SalesOrderHeader h WHERE h.ShipMethodID = (SELECT TOP 1 [OVERNIGHT J-FAST] FROM ShipMethod.ShipMethodID)
상수 누락에 대한 내 해결 방법은 옵티 마이저에 값에 대한 힌트를 제공하는 것입니다.
DECLARE @Constant INT = 123;
SELECT *
FROM [some_relation]
WHERE [some_attribute] = @Constant
OPTION( OPTIMIZE FOR (@Constant = 123))
이것은 실행 계획을 생성 할 때 변수를 상수 인 것처럼 처리하도록 쿼리 컴파일러에 지시합니다. 단점은 값을 두 번 정의해야한다는 것입니다.
아니요,하지만 좋은 오래된 명명 규칙을 사용해야합니다.
declare @MY_VALUE as int
FN_CONSTANT()
. 그렇게하면 그것이 무엇을하고 있는지 분명합니다.
T-SQL에는 상수에 대한 기본 제공 지원이 없습니다. SQLMenace의 접근 방식을 사용하여 시뮬레이션하거나 (다른 사람이 다른 것을 반환하기 위해 함수를 덮어 썼는지 여부를 확신 할 수는 없지만…) 여기에 제안 된대로 상수를 포함하는 테이블을 작성할 수 있습니다 . ConstantValue
열에 대한 변경 사항을 롤백하는 트리거를 작성할 수 있습니까?
SQL 함수를 사용하기 전에 다음 스크립트를 실행하여 성능 차이를 확인하십시오.
IF OBJECT_ID('fnFalse') IS NOT NULL
DROP FUNCTION fnFalse
GO
IF OBJECT_ID('fnTrue') IS NOT NULL
DROP FUNCTION fnTrue
GO
CREATE FUNCTION fnTrue() RETURNS INT WITH SCHEMABINDING
AS
BEGIN
RETURN 1
END
GO
CREATE FUNCTION fnFalse() RETURNS INT WITH SCHEMABINDING
AS
BEGIN
RETURN ~ dbo.fnTrue()
END
GO
DECLARE @TimeStart DATETIME = GETDATE()
DECLARE @Count INT = 100000
WHILE @Count > 0 BEGIN
SET @Count -= 1
DECLARE @Value BIT
SELECT @Value = dbo.fnTrue()
IF @Value = 1
SELECT @Value = dbo.fnFalse()
END
DECLARE @TimeEnd DATETIME = GETDATE()
PRINT CAST(DATEDIFF(ms, @TimeStart, @TimeEnd) AS VARCHAR) + ' elapsed, using function'
GO
DECLARE @TimeStart DATETIME = GETDATE()
DECLARE @Count INT = 100000
DECLARE @FALSE AS BIT = 0
DECLARE @TRUE AS BIT = ~ @FALSE
WHILE @Count > 0 BEGIN
SET @Count -= 1
DECLARE @Value BIT
SELECT @Value = @TRUE
IF @Value = 1
SELECT @Value = @FALSE
END
DECLARE @TimeEnd DATETIME = GETDATE()
PRINT CAST(DATEDIFF(ms, @TimeStart, @TimeEnd) AS VARCHAR) + ' elapsed, using local variable'
GO
DECLARE @TimeStart DATETIME = GETDATE()
DECLARE @Count INT = 100000
WHILE @Count > 0 BEGIN
SET @Count -= 1
DECLARE @Value BIT
SELECT @Value = 1
IF @Value = 1
SELECT @Value = 0
END
DECLARE @TimeEnd DATETIME = GETDATE()
PRINT CAST(DATEDIFF(ms, @TimeStart, @TimeEnd) AS VARCHAR) + ' elapsed, using hard coded values'
GO
2760ms elapsed, using function
| 2300ms elapsed, using local variable
| 2286ms elapsed, using hard coded values
|
5570 elapsed, using function
| 406 elapsed, using local variable
| 383 elapsed, using hard coded values
| 3893 elapsed, using function without schemabinding
select top 1 @m = cv_val from code_values where cv_id = 'C101'
동일 ... 'C201'
합니다. SQL-Server 2016에 모두있었습니다
변수 값에 대한 최적의 실행 계획을 얻으려면 동적 SQL 코드를 사용할 수 있습니다. 변수를 일정하게 만듭니다.
DECLARE @var varchar(100) = 'some text'
DECLARE @sql varchar(MAX)
SET @sql = 'SELECT * FROM table WHERE col = '''+@var+''''
EXEC (@sql)
열거 형 또는 단순 상수의 경우 단일 행이있는 뷰는 성능이 뛰어나고 컴파일 시간 검사 / 종속성 추적 (열 이름이 발생 함)이 있습니다.
Jared Ko의 블로그 게시물 https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/ 참조
보기 만들기
CREATE VIEW ShipMethods AS
SELECT CAST(1 AS INT) AS [XRQ - TRUCK GROUND]
,CAST(2 AS INT) AS [ZY - EXPRESS]
,CAST(3 AS INT) AS [OVERSEAS - DELUXE]
, CAST(4 AS INT) AS [OVERNIGHT J-FAST]
,CAST(5 AS INT) AS [CARGO TRANSPORT 5]
보기 사용
SELECT h.*
FROM Sales.SalesOrderHeader
WHERE ShipMethodID = ( select [OVERNIGHT J-FAST] from ShipMethods )
상수를 지원하는 빌드가 없기 때문에 내 솔루션은 매우 간단합니다.
이것은 지원되지 않기 때문에 :
Declare Constant @supplement int = 240
SELECT price + @supplement
FROM what_does_it_cost
나는 단순히 그것을
SELECT price + 240/*CONSTANT:supplement*/
FROM what_does_it_cost
분명히 이것은 모든 것 (후행 공백과 주석이없는 값)이 고유하다는 것에 의존합니다. 전역 검색 및 바꾸기로 변경할 수 있습니다.
데이터베이스 문헌에는 "상수 생성"과 같은 것이 없습니다. 상수는있는 그대로 존재하며 종종 값이라고합니다. 변수를 선언하고 여기에 값 (상수)을 할당 할 수 있습니다. 학문적 관점에서 :
DECLARE @two INT
SET @two = 2
여기서 @two는 변수이고 2는 값 / 상수입니다.
2
는 "컴파일 시간"에 할당 될 때 이진 값으로 변환됩니다. 인코딩 된 실제 값은 할당되는 데이터 유형 (int, char, ...)에 따라 다릅니다.
가장 좋은 대답은 스크립트 내에서, 즉 여러 GO 문 / 배치에서 사용할 임시 상수를 만드는 경우 요구 사항에 따라 SQLMenace에서 오는 것입니다.
tempdb에서 프로 시저를 생성하기 만하면 대상 데이터베이스에 영향을주지 않습니다.
이에 대한 실용적인 예는 논리적 스키마 버전을 포함하는 스크립트 끝에 제어 값을 쓰는 데이터베이스 생성 스크립트입니다. 파일 상단에는 변경 내역 등이 포함 된 주석이 있습니다. 그러나 실제로 대부분의 개발자는 아래로 스크롤하여 파일 하단의 스키마 버전을 업데이트하는 것을 잊을 것입니다.
위의 코드를 사용하면 데이터베이스 스크립트 (SSMS의 스크립트 생성 기능에서 복사)가 데이터베이스를 생성하지만 마지막에 사용되기 전에 맨 위에 보이는 스키마 버전 상수를 정의 할 수 있습니다. 이는 변경 내역 및 기타 댓글 옆에있는 개발자의 얼굴에 있기 때문에 업데이트 할 가능성이 매우 높습니다.
예를 들면 :
use tempdb
go
create function dbo.MySchemaVersion()
returns int
as
begin
return 123
end
go
use master
go
-- Big long database create script with multiple batches...
print 'Creating database schema version ' + CAST(tempdb.dbo.MySchemaVersion() as NVARCHAR) + '...'
go
-- ...
go
-- ...
go
use MyDatabase
go
-- Update schema version with constant at end (not normally possible as GO puts
-- local @variables out of scope)
insert MyConfigTable values ('SchemaVersion', tempdb.dbo.MySchemaVersion())
go
-- Clean-up
use tempdb
drop function MySchemaVersion
go
WITH SCHEMABINDING
이것을 '실제'상수로 바꿔야합니다 (UDF가 SQL에서 결정적으로 보이도록하기위한 요구 사항). 즉, 캐시 된 상태 여야합니다. 그래도 +1.