Есть ли способ сделать переменную TSQL постоянной?
есть ли способ сделать переменную TSQL постоянной?
12 ответов:
нет, но вы можете создать функцию и записать ее туда и использовать.
вот пример:
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 полностью игнорирует значение представления, но все же строит план выполнения на основе его значение. Этот план выполнения даже не показывает соединение с представлением!
в T-SQL нет встроенной поддержки констант. Вы можете использовать подход SQLMenace для его моделирования (хотя вы никогда не можете быть уверены, что кто-то другой перезаписал функцию, чтобы вернуть что-то еще...), или, возможно, написать таблицу, содержащую константы,как было предложено здесь. Возможно, написать триггер, который откатывает любые изменения в ?
перед использованием функции 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 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]
используйте
SELECT h.* FROM Sales.SalesOrderHeader h JOIN ShipMethod.ShipMethodID const ON h.ShipMethodID = const.[OVERNIGHT J-FAST]
Ладно, давайте посмотрим
константы неизменные значения, которые известны во время компиляции и не меняются в течение жизни программы
это означает, что вы никогда не можете иметь константу в 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