Pregunta

¿Hay alguna manera de hacer que una variable TSQL sea constante?

¿Fue útil?

Solución

No, pero puedes crear una función, codificarla allí y usarla.

Aquí hay un ejemplo:

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

SELECT dbo.fnConstant()

Otros consejos

Mi solución para la falta de constantes es dar pistas sobre el valor al optimizador.

DECLARE @Constant INT = 123;

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

Esto le indica al compilador de consultas que trate la variable como si fuera una constante al crear el plan de ejecución.La desventaja es que tienes que definir el valor dos veces.

Utilice pseudoconstantes: http://blogs.msdn.com/b/sql_server_appendix_z/archive/2013/09/16/sql-server-variables-parameters-or-literals-or-constants.aspx

Las pseudoconstantes no son variables ni parámetros.En cambio, son simplemente vistas con una fila y suficientes columnas para soportar sus constantes.Con estas reglas simples, el motor SQL ignora completamente el valor de la vista, pero aún construye un plan de ejecución basado en su valor.¡El plan de ejecución ni siquiera muestra una unión a la vista!

No, pero se deben utilizar las antiguas convenciones de nomenclatura.

declare @MY_VALUE as int

No hay soporte integrado para constantes en T-SQL.Podrías usar el enfoque de SQLMenace para simularlo (aunque nunca podrás estar seguro de si alguien más ha sobrescrito la función para devolver algo más...), o posiblemente escribir una tabla que contenga constantes. como se sugiere aquí.Tal vez escriba un activador que revierta cualquier cambio en el ConstantValue ¿columna?

Antes de utilizar una función SQL, ejecute el siguiente script para ver las diferencias en el rendimiento:

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 está interesado en obtener un plan de ejecución óptimo para un valor en la variable, puede utilizar un código SQL dinámico.Hace que la variable sea constante.

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

Para enumeraciones o constantes simples, una vista con una sola fila tiene un gran rendimiento y verificación del tiempo de compilación/seguimiento de dependencia (porque es un nombre de columna)

Ver la publicación del blog de Jared Ko https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/

crear la vista

 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]

usa la vista

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

Bien, veamos

Las constantes son valores inmutables que se conocen en el momento de la compilación y no cambian durante la vida del programa.

eso significa que nunca podrás tener una constante en SQL Server

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

el valor acaba de cambiar

Dado que no hay soporte integrado para constantes, mi solución es muy simple.

Dado que esto no es compatible:

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

Simplemente lo convertiría a

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

Obviamente, esto depende de que todo (el valor sin espacio final y el comentario) sea único.Cambiarlo es posible con una búsqueda y reemplazo global.

No existe nada parecido a "crear una constante" en la literatura sobre bases de datos.Las constantes existen tal como son y a menudo se les llama valores.Se puede declarar una variable y asignarle un valor (constante).Desde una visión escolástica:

DECLARE @two INT
SET @two = 2

Aquí @two es una variable y 2 es un valor/constante.

La mejor respuesta es de SQLMenace según el requisito si se trata de crear una constante temporal para usar dentro de los scripts, es decir.en múltiples declaraciones/lotes GO.

Simplemente cree el procedimiento en tempdb y no tendrá ningún impacto en la base de datos de destino.

Un ejemplo práctico de esto es un script de creación de base de datos que escribe un valor de control al final del script que contiene la versión del esquema lógico.En la parte superior del archivo hay algunos comentarios con el historial de cambios, etc.Pero en la práctica, la mayoría de los desarrolladores olvidarán desplazarse hacia abajo y actualizar la versión del esquema en la parte inferior del archivo.

El uso del código anterior permite definir una constante de versión de esquema visible en la parte superior antes de que el script de la base de datos (copiado de la función de generación de scripts de SSMS) cree la base de datos, pero se usa al final.Esto está justo en la cara del desarrollador junto al historial de cambios y otros comentarios, por lo que es muy probable que lo actualicen.

Por ejemplo:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top