95 votes

Est-il possible de rendre une variable TSQL constante?

Est-il possible de rendre une variable TSQL constante?

63voto

SQLMenace Points 68670

Non, mais vous pouvez créer une fonction et la coder en dur là-bas et l'utiliser

Voici un exemple

 create function fnConstant()
returns int
as
begin
return 2
end
go

select dbo.fnConstant()
 

27voto

John Nilsson Points 4650

Ma solution de rechange aux constantes manquantes consiste à donner des indications sur la valeur pour l'optimiseur.

 DECLARE @Consant INT = 123;

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

Cela indique au compilateur de requêtes de traiter la variable comme s'il s'agissait d'une constante lors de la création du plan d'exécution. L'inconvénient est que vous devez définir la valeur deux fois.

10voto

jason saldo Points 5036

Non, mais les bonnes anciennes conventions de nommage devraient être utilisées.

 declare @MY_VALUE as int
 

8voto

Sören Kuklau Points 9445

Il n'y a pas de support intégré pour les constantes dans T-SQL. Vous pouvez utiliser l'approche de SQLMenace pour la simuler (même si vous ne pouvez jamais être sûr que quelqu'un d'autre a écrasé la fonction pour renvoyer quelque chose d'autre…), ou éventuellement écrire une table contenant des constantes, comme suggéré ici . Peut-être écrire un déclencheur qui annule les modifications apportées à la colonne ConstantValue ?

7voto

Robert Points 31

Avant d'utiliser une fonction SQL, exécutez le script suivant pour voir les différences de performances:

 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
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X