Pergunta

Existe uma maneira de tornar uma variável TSQL constante?

Foi útil?

Solução

Não, mas você pode criar uma função, codificá-la e usá-la.

Aqui está um exemplo:

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

SELECT dbo.fnConstant()

Outras dicas

Minha solução alternativa para constantes ausentes é dar dicas sobre o valor ao otimizador.

DECLARE @Constant INT = 123;

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

Isso informa ao compilador de consulta para tratar a variável como se fosse uma constante ao criar o plano de execução.A desvantagem é que você precisa definir o valor duas vezes.

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

Pseudoconstantes não são variáveis ​​ou parâmetros.Em vez disso, são simplesmente visualizações com uma linha e colunas suficientes para apoiar suas constantes.Com essas regras simples, o mecanismo SQL ignora completamente o valor da visualização, mas ainda cria um plano de execução com base em seu valor.O plano de execução nem mostra uma junção com a visualização!

Não, mas as boas e velhas convenções de nomenclatura devem ser usadas.

declare @MY_VALUE as int

Não há suporte integrado para constantes no T-SQL.Você poderia usar a abordagem do SQLMenace para simulá-lo (embora você nunca possa ter certeza se alguém substituiu a função para retornar outra coisa...), ou possivelmente escrever uma tabela contendo constantes, como sugerido aqui.Talvez escreva um gatilho que reverta quaisquer alterações no ConstantValue coluna?

Antes de usar uma função SQL, execute o seguinte script para ver as diferenças de desempenho:

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

Se você estiver interessado em obter um plano de execução ideal para um valor na variável, poderá usar um código SQL dinâmico.Isso torna a variável constante.

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

Para enums ou constantes simples, uma visualização com uma única linha tem ótimo desempenho e verificação de tempo de compilação/rastreamento de dependência (porque é um nome de coluna)

Veja a postagem do blog de Jared Ko https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/

criar a visualização

 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]

usar a visualização

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

Ok, vamos ver

Constantes são valores imutáveis ​​que são conhecidos em tempo de compilação e não mudam durante a vida do programa

isso significa que você nunca pode ter uma constante no SQL Server

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

o valor acabou de mudar

Como não há suporte integrado para constantes, minha solução é muito simples.

Como isso não é compatível:

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

Eu simplesmente converteria para

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

Obviamente, isso depende de que tudo (o valor sem espaço à direita e o comentário) seja único.Alterá-lo é possível com uma pesquisa e substituição global.

Não existe "criação de uma constante" na literatura de banco de dados.As constantes existem como são e geralmente são chamadas de valores.Pode-se declarar uma variável e atribuir um valor (constante) a ela.Do ponto de vista escolar:

DECLARE @two INT
SET @two = 2

Aqui @two é uma variável e 2 é um valor/constante.

A melhor resposta é do SQLMenace de acordo com o requisito se for criar uma constante temporária para uso em scripts, ou seja.em várias instruções/lotes GO.

Basta criar o procedimento no tempdb para não ter impacto no banco de dados de destino.

Um exemplo prático disso é um script de criação de banco de dados que grava um valor de controle no final do script contendo a versão do esquema lógico.No topo do arquivo estão alguns comentários com histórico de alterações, etc.Mas, na prática, a maioria dos desenvolvedores esquecerá de rolar para baixo e atualizar a versão do esquema na parte inferior do arquivo.

O uso do código acima permite que uma constante de versão do esquema visível seja definida na parte superior antes que o script do banco de dados (copiado do recurso de geração de scripts do SSMS) crie o banco de dados, mas seja usado no final.Isso está bem na cara do desenvolvedor, ao lado do histórico de alterações e outros comentários, então é muito provável que eles o atualizem.

Por exemplo:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top