当前位置:  开发笔记 > 编程语言 > 正文

有没有办法让TSQL变量保持不变?

如何解决《有没有办法让TSQL变量保持不变?》经验,为你挑选了8个好方法。

有没有办法让TSQL变量保持不变?



1> SQLMenace..:

不,但你可以在那里创建一个函数并对其进行硬编码并使用它.

这是一个例子:

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

SELECT dbo.fnConstant()


`WITH SCHEMABINDING`**应该**将它转换为'实数'常量(要求UDF在SQL中被视为确定性).即它应该被缓存.仍然是+1.

2> John Nilsson..:

我对缺少常量的解决方法是给优化器提供有关值的提示.

DECLARE @Constant INT = 123;

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

这告诉查询编译器在创建执行计划时将变量视为常量.缺点是你必须定义两次值.



3> 小智..:

使用伪常量:http://blogs.msdn.com/b/sql_server_appendix_z/archive/2013/09/16/sql-server-variables-parameters-or-literals-or-constants.aspx

伪常数不是变量或参数.相反,它们只是一行的视图,以及足够的列来支持您的常量.使用这些简单的规则,SQL引擎完全忽略视图的值,但仍然根据其值构建执行计划.执行计划甚至没有显示视图的连接!



4> jason saldo..:

不,但应使用良好的旧命名约定.

declare @MY_VALUE as int



5> Sören Kuklau..:

T-SQL中没有对常量的内置支持.您可以使用SQLMenace的方法来模拟它(尽管您永远无法确定其他人是否已覆盖该函数以返回其他内容...),或者可能会编写一个包含常量的表,如此处所示.也许写一个触发器来回滚ConstantValue列的任何更改?



6> 小智..:

在使用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


这是相当古老的,但在这里参考是在我的服务器上执行的结果:| `2760ms过去了,使用函数`| `2300ms过去了,使用局部变量`| `经过2286ms,使用硬编码值|
在开发型笔记本电脑上,具有两个没有模式绑定的附加功能。使用功能5过去了5570 使用本地变量,“ 406已逝去” 使用硬编码值,“ 383已逝去” 使用了没有模式绑定的函数,3893过去了

7> 小智..:

如果您有兴趣为变量中的值获取最佳执行计划,则可以使用动态sql代码.它使变量保持不变.

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



8> user1778606..:

对于枚举或简单常量,具有单行的视图具有出色的性能和编译时检查/依赖性跟踪(导致其列名)

请参阅Jared Ko的博客文章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  )

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有