Есть ли способ сделать константу переменной TSQL постоянной? - PullRequest
77 голосов
/ 25 августа 2008

Есть ли способ сделать константу переменной TSQL постоянной?

Ответы [ 12 ]

50 голосов
/ 25 августа 2008

Нет, но вы можете создать функцию и жестко закодировать ее там и использовать ее.

Вот пример:

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

SELECT dbo.fnConstant()
17 голосов
/ 04 октября 2012

Мой обходной путь к отсутствующим константам - дать подсказки оптимизатору.

DECLARE @Constant INT = 123;

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

Это говорит компилятору запроса обрабатывать переменную, как если бы она была константой при создании плана выполнения. Недостатком является то, что вы должны определить значение дважды.

15 голосов
/ 03 сентября 2015

Используйте псевдо-константы: http://blogs.msdn.com/b/sql_server_appendix_z/archive/2013/09/16/sql-server-variables-parameters-or-literals-or-constants.aspx

Псевдоконстанты не являются переменными или параметрами. Вместо этого они просто просмотры с одной строкой и достаточным количеством столбцов для поддержки вашего константы. С этими простыми правилами SQL Engine полностью игнорирует значение представления, но по-прежнему строит план выполнения на основе его значение. План выполнения даже не показывает присоединение к представлению!

9 голосов
/ 25 августа 2008

Нет, но следует использовать старые добрые соглашения об именах.

declare @MY_VALUE as int
7 голосов
/ 25 августа 2008

В T-SQL нет встроенной поддержки констант. Вы можете использовать подход SQLMenace для его моделирования (хотя вы никогда не можете быть уверены, что кто-то другой перезаписал функцию, чтобы вернуть что-то еще ...), или, возможно, напишите таблицу, содержащую константы , как предложено здесь . Возможно, напишите триггер, который откатывает любые изменения в столбце ConstantValue?

6 голосов
/ 31 декабря 2012

Перед использованием функции SQL запустите следующий скрипт, чтобы увидеть различия в производительности:

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
5 голосов
/ 28 декабря 2017

Для перечислений или простых констант представление с одной строкой обладает высокой производительностью и проверкой времени компиляции / отслеживанием зависимостей (вызывает имя столбца)

См. Сообщение в блоге Джареда Ко https://blogs.msdn.microsoft.com/sql_server_appendix_z/2013/09/16/sql-server-variables-parameters-or-literals-or-constants/

создать вид

 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]

использовать вид

SELECT h.*
FROM Sales.SalesOrderHeader 
WHERE ShipMethodID = ( select [OVERNIGHT J-FAST] from ShipMethods  )
5 голосов
/ 23 сентября 2016

Если вы заинтересованы в получении оптимального плана выполнения для значения в переменной, вы можете использовать динамический SQL-код. Делает переменную постоянной.

DECLARE @var varchar(100) = 'some text'
DECLARE @sql varchar(MAX)
SET @sql = 'SELECT * FROM table WHERE col = '''+@var+''''
EXEC (@sql)
2 голосов
/ 25 августа 2008

Хорошо, давайте посмотрим

Константы - это неизменные значения, которые известны во время компиляции и не изменяются в течение жизни программы

это означает, что вы никогда не можете иметь константу в SQL Server

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

значение только что изменилось

1 голос
/ 29 декабря 2017

Поскольку встроенная поддержка констант отсутствует, мое решение очень простое.

Так как это не поддерживается:

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

Я бы просто преобразовал его в

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

Очевидно, что это зависит от уникальности всего значения (значение без конечного пробела и комментария) Изменить его можно с помощью глобального поиска и замены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...