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

StackOverflow https://stackoverflow.com/questions/26652

  •  09-06-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

Вот такой пример:

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

SELECT dbo.fnConstant()

Другие советы

Мой обходной путь к отсутствующим константам заключается в том, чтобы дать подсказки оптимизатору о значении.

DECLARE @Constant INT = 123;

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

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

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

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

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

declare @MY_VALUE as int

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

Перед использованием функции 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

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

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

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

Смотрите запись в блоге Джареда Ко 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  )

Ладно, давайте посмотрим

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

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

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

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

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

Поскольку это не поддерживается:

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

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

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

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

В литературе по базам данных нет такого понятия, как "создание константы".Константы существуют такими, какие они есть, и их часто называют значениями.Можно объявить переменную и присвоить ей значение (константу).С точки зрения схоластики:

DECLARE @two INT
SET @two = 2

Здесь @two - это переменная, а 2 - значение / константа.

Лучший ответ - от SQLMenace в соответствии с требованием, если это создание временной константы для использования в скриптах, т.е.через несколько инструкций / пакетов GO.

Просто создайте процедуру в базе данных tempdb, тогда вы не окажете никакого влияния на целевую базу данных.

Одним из практических примеров этого является сценарий создания базы данных, который записывает управляющее значение в конце сценария, содержащего версию логической схемы.В верхней части файла находятся некоторые комментарии с историей изменений и т.д...Но на практике большинство разработчиков забудут прокрутить страницу вниз и обновить версию схемы в нижней части файла.

Использование приведенного выше кода позволяет определить видимую константу версии схемы вверху до того, как скрипт базы данных (скопированный из функции создания сценариев SSMS) создаст базу данных, но используемый в конце.Это находится прямо перед лицом разработчика рядом с историей изменений и другими комментариями, так что они, скорее всего, обновят его.

Например:

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top