2008-08-25 6 views

Respuesta

45

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

Aquí se muestra un ejemplo:

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

SELECT dbo.fnConstant() 
+6

'WITH SCHEMABINDING' ** debe ** convertir esto en una constante 'real' (un requisito para que un UDF sea visto como determinista en SQL). Es decir. debería aterrizar en la memoria caché. Aún así, +1. –

0

No existe la "creación de una constante" en la literatura de la base de datos. Las constantes existen tal como están y a menudo se llaman valores. Uno puede declarar una variable y asignarle un valor (constante). Desde una vista escolástica:

DECLARE @two INT 
SET @two = 2 

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

+0

Pruebe las respuestas de Michal D. y John Nilsson para un aumento en el rendimiento también. –

7

No, pero los buenos viejos convenciones de nomenclatura se debe utilizar.

declare @MY_VALUE as int 
+0

Bueno, es realmente viejo. ¿Por qué piensas que es bueno? –

+0

@VictorYarema porque a veces la convención es todo lo que necesita. Y porque a veces no tienes otra opción buena. Ahora, aparte de eso, la respuesta de SQLMenace se ve mejor, estaré de acuerdo contigo. Aun así, el nombre de las funciones debe seguir la convención para constantes, IMO. Debería llamarse 'FN_CONSTANT()'. De esa forma está claro lo que está haciendo. – tfrascaroli

+0

Esto solo no ayudará cuando desee el beneficio de rendimiento. Pruebe las respuestas de Michal D. y John Nilsson para mejorar el rendimiento también. –

1

Está bien, vamos a ver

Las constantes son valores inmutables que son conocidos en tiempo de compilación y no cambian durante la vida del programa

que significa que nunca puede 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

7

no hay soporte integrado para constantes en T-SQL. Puede usar el enfoque de SQLMenace para simularlo (aunque nunca puede estar seguro de si alguien más ha sobreescrito la función para devolver algo más ...), o posiblemente escriba una tabla que contenga constantes, as suggested over here. ¿Quizás escriba un activador que revierte los cambios a la columna ConstantValue?

13

Mi solución a los constantes faltantes es dar pistas sobre el valor para el optimizador.

DECLARE @Constant INT = 123; 

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

Esto le dice al compilador de consultas que trate la variable como si fuera una constante al crear el plan de ejecución. El lado negativo es que debe definir el valor dos veces.

-1

La mejor respuesta es de SQLMenace según el requisito si se trata de crear una constante temporal para su uso dentro de scripts, es decir, a través de múltiples sentencias/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 una secuencia de comandos create de base de datos que escribe un valor de control al final de la secuencia de comandos que contiene la versión de esquema lógico. En la parte superior del archivo hay algunos comentarios con historial de cambios, etc. ... Pero en la práctica, la mayoría de los desarrolladores se olvidarán de 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 base de datos (copiado de la característica de generación de scripts de SSMS) crea la base de datos pero se usa al final. Esto está justo frente al 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 
5

Antes de utilizar una función de SQL ejecute la siguiente secuencia de comandos 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 
+2

Esto es bastante antiguo, pero para referencia aquí está el resultado cuando se ejecuta en mi servidor: | '2760ms transcurridos, usando la función' | '2300ms transcurridos, utilizando la variable local' | '2286ms transcurridos, utilizando valores codificados de forma rígida' | – z00l

+0

En una computadora portátil dev, con dos funciones adicionales sin enlace de esquema. '' '5570 transcurrido, usando la función' '' | '' '406 transcurrido, usando la variable local''' | '' '383 transcurrido, utilizando valores codificados''' | '' '3893 transcurrido, usando la función sin schemabinding''' – user1778606

+0

Para comparación, una instrucción de selección simple tomó 4110ms donde las instrucciones de selección alternaron entre' '' seleccionar top 1 @m = cv_val de code_values ​​donde cv_id = 'C101' '' ' y el mismo '' '... 'C201'' '' donde code_values ​​es una tabla de diccionario con 250 vars, había todo en SQL-Server 2016 – user1778606

12

Use pseudo-constantes: 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 o parámetros. En su lugar, son simples vistas con una fila y suficientes columnas para admitir sus constantes . Con estas reglas simples, SQL Engine ignora por completo el valor de la vista, pero sigue construyendo un plan de ejecución basado en su valor . ¡El plan de ejecución ni siquiera muestra un join a la vista!

4

Si está interesado en obtener un plan de ejecución óptimo para un valor en la variable, puede usar un código sql dinámico. Hace la variable constante.

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

Así es como lo hago y ofrece un gran impulso al rendimiento para las consultas que involucran constantes . –

1

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

el blog de Ver 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 ShipMethod.ShipMethodID 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] 

uso de la vista

SELECT h.* 
FROM Sales.SalesOrderHeader h 
JOIN ShipMethod.ShipMethodID const 
    ON h.ShipMethodID = const.[OVERNIGHT J-FAST] 
1

Dado que no existe una construcción en soporte de 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 sería convertirlo en

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

Obviamente, esto depende de todo el asunto (el valor sin arrastrando el espacio y el comentario) para ser único. Cambiarlo es posible con una búsqueda y reemplazo global.

Cuestiones relacionadas