Question

Existe-t-il un moyen de rendre constante une variable TSQL ?

Était-ce utile?

La solution

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

Voici un exemple:

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

SELECT dbo.fnConstant()

Autres conseils

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

DECLARE @Constant 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.

Utilisez des pseudo-constantes : http://blogs.msdn.com/b/sql_server_appendix_z/archive/2013/09/16/sql-server-variables-parameters-or-literals-or-constants.aspx

Les pseudo-constantes ne sont pas des variables ou des paramètres.Au lieu de cela, ce sont simplement des vues avec une ligne et suffisamment de colonnes pour soutenir vos constantes.Avec ces règles simples, le moteur SQL ignore complètement la valeur de la vue mais construit toujours un plan d'exécution en fonction de sa valeur.Le plan d'exécution ne montre même pas de jointure à la vue !

Non, mais les bonnes vieilles conventions de dénomination doivent être utilisées.

declare @MY_VALUE as int

Il n'existe pas de prise en charge intégrée des 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 autre chose…), ou éventuellement écrire une table contenant des constantes, comme suggéré ici.Écrivez peut-être un déclencheur qui annule toute modification apportée au ConstantValue colonne?

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

Si vous souhaitez obtenir un plan d'exécution optimal pour une valeur de la variable, vous pouvez utiliser un code SQL dynamique.Cela rend la variable constante.

DECLARE @var varchar(100) = 'some text'
DECLARE @sql varchar(MAX)
SET @sql = 'SELECT * FROM table WHERE col = '''+@var+''''
EXEC (@sql)

Pour les énumérations ou les constantes simples, une vue avec une seule ligne offre d'excellentes performances et une vérification du temps de compilation/suivi des dépendances (car c'est un nom de colonne)

Voir le billet de blog de Jared Ko https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/

créer la vue

 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]

utiliser la vue

SELECT h.*
FROM Sales.SalesOrderHeader 
WHERE ShipMethodID = ( select [OVERNIGHT J-FAST] from ShipMethods  )

D'accord, voyons voir

Les constantes sont des valeurs immuables qui sont connues au moment de la compilation et ne changent pas pendant toute la durée de vie du programme.

cela signifie que vous ne pouvez jamais avoir de constante dans SQL Server

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

la valeur vient de changer

Puisqu’il n’y a pas de support intégré pour les constantes, ma solution est très simple.

Puisque cela n'est pas pris en charge :

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

Je le convertirais simplement en

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

Évidemment, cela repose sur le fait que l'ensemble (la valeur sans espace de fin et le commentaire) soit unique.Le changer est possible avec une recherche et un remplacement global.

Il n’existe pas de « création d’une constante » dans la littérature sur les bases de données.Les constantes existent telles quelles et sont souvent appelées valeurs.On peut déclarer une variable et lui attribuer une valeur (constante).D'un point de vue scolaire :

DECLARE @two INT
SET @two = 2

Ici, @two est une variable et 2 est une valeur/constante.

La meilleure réponse vient de SQLMenace selon l'exigence s'il s'agit de créer une constante temporaire à utiliser dans les scripts, c'est-à-diresur plusieurs instructions/lots GO.

Créez simplement la procédure dans tempdb, vous n’aurez alors aucun impact sur la base de données cible.

Un exemple pratique de ceci est un script de création de base de données qui écrit une valeur de contrôle à la fin du script contenant la version du schéma logique.En haut du fichier se trouvent quelques commentaires avec l'historique des modifications, etc...Mais en pratique, la plupart des développeurs oublieront de faire défiler vers le bas et de mettre à jour la version du schéma au bas du fichier.

L'utilisation du code ci-dessus permet de définir une constante de version de schéma visible en haut avant que le script de base de données (copié à partir de la fonctionnalité de génération de scripts de SSMS) ne crée la base de données mais est utilisée à la fin.Cela se trouve directement devant le développeur, à côté de l'historique des modifications et d'autres commentaires, il est donc très probable qu'il le mette à jour.

Par exemple:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top