質問
TSQL変数を定数にする方法はありますか?
解決
いいえ、しかし、関数を作成してそこにハードコーディングしてそれを使用することはできます。
以下に例を示します。
CREATE FUNCTION fnConstant()
RETURNS INT
AS
BEGIN
RETURN 2
END
GO
SELECT dbo.fnConstant()
他のヒント
欠落している定数に対する私の回避策は、オプティマイザに値に関するヒントを与えることです。
DECLARE @Constant INT = 123;
SELECT *
FROM [some_relation]
WHERE [some_attribute] = @Constant
OPTION( OPTIMIZE FOR (@Constant = 123))
これにより、実行プランの作成時に変数を定数であるかのように扱うようにクエリ コンパイラに指示されます。欠点は、値を 2 回定義する必要があることです。
擬似定数は変数やパラメータではありません。代わりに、それらは単に1つの行と、定数をサポートするのに十分な列でビューを見ることです。これらの単純なルールを使用すると、SQLエンジンはビューの価値を完全に無視しますが、その価値に基づいて実行計画を構築します。実行計画にはビューへの結合さえ示されていません。
いいえ、ただし古き良き命名規則を使用する必要があります。
declare @MY_VALUE as int
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
変数内の値に対する最適な実行プランを取得することに興味がある場合は、動的 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 )
わかりました、見てみましょう
定数は不変の値であり、コンパイル時に既知であり、プログラムの存続期間中は変更されません。
つまり、SQL Server では定数を使用することはできません。
declare @myvalue as int
set @myvalue = 5
set @myvalue = 10--oops we just changed it
値が変更されたばかりです
定数のサポートが組み込まれていないため、私の解決策は非常に単純です。
これはサポートされていないため、次のようになります。
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 は値/定数です。
最良の答えは、スクリプト内で使用する一時定数を作成する場合、要件に従って SQLMenace からのものです。複数の GO ステートメント/バッチにわたって。
tempdb にプロシージャを作成するだけであれば、ターゲット データベースには影響しません。
この実際的な例の 1 つは、論理スキーマのバージョンを含むスクリプトの最後に制御値を書き込むデータベース作成スクリプトです。ファイルの先頭には、変更履歴などを含むコメントがいくつかあります。しかし、実際には、ほとんどの開発者は、下にスクロールしてファイルの下部にあるスキーマ バージョンを更新することを忘れてしまいます。
上記のコードを使用すると、データベース スクリプト (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