【发布时间】:2014-01-15 15:32:54
【问题描述】:
在最终将结果集呈现给用户之前,我对表变量做了大量工作。例如,我可能会从许多不同的表中提取大量列,如下所示:
DECLARE @tmp TABLE
(
ID int,
username nvarchar(50), -- data taken from tbl_Users
site nvarchar(50), -- data taken from tbl_Sites
region nvarchar(100), -- data taken from tbl_Regions
currency nvarchar(5) -- data taken from tbl_Currencies
)
我花了很多时间查看对象资源管理器以确保列的数据长度正确(与原始表匹配)。有时,如果我更改表架构但不更新所有过程,我可能会遇到截断错误。
采取懒惰的方法并这样做有什么问题:
DECLARE @tmp TABLE
(
ID int,
username nvarchar(max),
site nvarchar(max),
region nvarchar(max),
currency nvarchar(max)
)
nvarchar(max) 是否真的用尽了更多的内存,或者这是根据数据大小分配的内存?还有其他陷阱吗?
请注意,我知道第三方工具可以跳转到定义,但这不是我要问的。
更新
重复的问题有价值,但问题不完全相同恕我直言。副本围绕实际表格的设计,而不是表格变量。但是,答案有一些优点,即:
- nvarchar(max) 与 nvarchar(8000) 在 8000+ 数据长度之前在资源使用方面没有区别
- 业务逻辑层依赖于结构和有意义数据,因此指定与原始数据互补的列大小会提供价值
从这个意义上说,在表变量中使用nvarchar(max) 而不是nvarchar(n) 似乎很好,但在某些 环境中它存在可靠性和性能风险。如果您认为这应该被删除,那么就足够公平了(但请不要争论我感谢所有的意见!)
【问题讨论】:
-
这是用户定义类型应该解决的问题,但鉴于您无法在定义后重新定义类型,因此在可能发生重新定义的模式中使用它们会很痛苦,而您想要保留数据(如果它们确实有效,您将能够在两个表中都有
username类型的username,并且类型定义将定义基本类型(varchar),长度(50)等) -
我也使用(最大)快捷方式。我认为唯一的问题是您可以将更多的文本连接到变量中,而不是最终放入列中。 imo不是一个大问题。
-
您通常在这些表变量中处理多少行?如果数量很少,请将您的优化工作集中在其他地方,恕我直言。如果数量很大,请测试。
-
行数是一个重要的决定因素,正如 Aaron 指出的那样。如果您要处理的行数超过少量(小可能是 10-100 之间的任何地方),您最好查看临时表而不是变量。除了插入最终目的地时数据长度不匹配的问题之外,整个问题可能没有实际意义。
-
谁清理了所有的争论?!?
标签: sql-server tsql sql-server-2012