96

TSQL 変数を定数にする方法はありますか?

4

12 に答える 12

63

No, but you can create a function and hardcode it in there and use that.

Here is an example:

CREATE FUNCTION fnConstant()
RETURNS INT
AS
BEGIN
    RETURN 2
END
GO

SELECT dbo.fnConstant()
于 2008-08-25T19:05:30.060 に答える
27

不足している定数に対する私の回避策は、値に関するヒントをオプティマイザーに与えることです。

DECLARE @Constant INT = 123;

SELECT * 
FROM [some_relation] 
WHERE [some_attribute] = @Constant
OPTION( OPTIMIZE FOR (@Constant = 123))

これにより、クエリ コンパイラは、実行プランの作成時に変数を定数であるかのように処理するように指示されます。欠点は、値を 2 回定義する必要があることです。

于 2012-10-04T08:31:47.867 に答える
10

No, but good old naming conventions should be used.

declare @MY_VALUE as int
于 2008-08-25T19:15:26.450 に答える
8

T-SQL には、定数の組み込みサポートはありません。SQLMenace のアプローチを使用してそれをシミュレートすることもできます (ただし、他の誰かが関数を上書きして別の何かを返すかどうかはわかりませんが…)、ここで提案されているように、定数を含むテーブルを作成することもできます。ConstantValueおそらく、列への変更をロールバックするトリガーを作成しますか?

于 2008-08-25T19:16:37.523 に答える
7

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
于 2012-12-31T00:40:05.297 に答える
3

わかりました、見てみましょう

定数は、コンパイル時に認識され、プログラムの存続期間中変更されない不変の値です。

つまり、SQL Server で定数を使用することはできません。

declare @myvalue as int
set @myvalue = 5
set @myvalue = 10--oops we just changed it

値が変更されただけ

于 2008-08-25T19:16:16.820 に答える
1

定数のサポートは組み込まれていないため、私の解決策は非常に単純です。

これはサポートされていないため:

Declare Constant @supplement int = 240
SELECT price + @supplement
FROM   what_does_it_cost

私は単にそれをに変換します

SELECT price + 240/*CONSTANT:supplement*/
FROM   what_does_it_cost

明らかに、これは全体 (末尾のスペースとコメントを除いた値) が一意であることに依存しています。グローバル検索と置換で変更できます。

于 2017-12-29T16:40:13.193 に答える
0

データベースの文献には「定数を作成する」というようなものはありません。定数はそのまま存在し、しばしば値と呼ばれます。変数を宣言して、それに値 (定数) を割り当てることができます。学問的な観点から:

DECLARE @two INT
SET @two = 2

ここで @two は変数で、2 は値/定数です。

于 2008-08-25T19:05:04.883 に答える
-1

最良の答えは、スクリプト内で、つまり複数の GO ステートメント/バッチで使用する一時定数を作成する場合の要件に従って、SQLMenace からのものです。

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
于 2012-12-03T14:56:23.017 に答える