小编Geo*_*tis的帖子

什么时候 nvarchar(Max) = nvarchar(4000)?

SO 和其他网站上有多个帖子明确指出了最大长度nvarchar(max)为 2GB。然而,我在互联网和现实生活中也看到了很多混乱,它实际上是 Unicode 中的 8000/4000。

我想知道什么事情可以改变这个事实,或者可能导致某人错误地假设这一点。

我已经收集的一些建议/部分答案:

  1. 是否有旧的 SQL Server 版本仅支持最多 4000 个?
  2. 当将nvarchar(max)变量/列分配给非最大尺寸组件的串联时,我们必须将所有内容都nvarchar(max)显式转换吗?下面展示了一个奇怪的示例,其中文本返回函数需要转换,而文字的 N 可以省略:

    declare @s nvarchar(max) 
    select @s = convert(nvarchar(max), replicate('.', 8000)) + N'Hi!'
    select len(@s) -- returns 8003
    
    declare @s nvarchar(max) 
    select @s = replicate('.', 8000) + N'Hi!' 
    select len(@s) -- returns 4000
    
    declare @s nvarchar(max) 
    select @s = convert(nvarchar(max), replicate('.', 8000)) + 'Hi!' 
    select len(@s) -- returns 8003
    
    Run Code Online (Sandbox Code Playgroud)
  3. 有办法禁用该功能吗?与此有sp_tableoption @OptionName=large value types out of row …

t-sql sql-server nvarchar

7
推荐指数
1
解决办法
1万
查看次数

在proc之外,相同的查询运行得更快

我们有一个特定的查询,在proc内部运行得慢得多.我必须在这里添加它,它被包含在一个两级游标中.但是,两个游标都有一行的迭代结果集.

让我先说明我们尝试过但失败的事情:

  • 使用选项(重新编译)和选项(optiimize for(@var UNKNOWN)避免参数嗅探
  • 这个帖子.似乎是问题的变量实际上是本地变量而不是proc参数.

这是从proc/cursors内部获取的查询.

 select @tpdim1 = dim1, @tpdim2 = dim2, @typecalc = typecalc
    from loyalty_policy where code=@loop2_loyalty_policy
Run Code Online (Sandbox Code Playgroud)

注意:@ loop2_loyalty_policy是取自内部游标结果的var,并且有一个值.code是PK到loyalty_policy桌子.因此,@ tpdim1和@tpdim2各有一个值.

SET STATISTICS PROFILE ON 
SET STATISTICS    xml on           
                  insert into @tbl_loyal_loop2 (cnt, store, map, pda, insdate, line, item, loyalty_policy_data, loyal_calc, loyalty_policy)
                  select @cnt, t.store, t.map, t.pda, t.insdate, t.line, t.item, ld.tab_id,  
                  case @typecalc
                        when 1 then convert(bigint,round(isnull(t.valueFromTran,0.00) * ld.value , 0 ) )
                        when 2 then convert(bigint,round(isnull(t.netvalue,0.00) * ld.value , 0 ) …
Run Code Online (Sandbox Code Playgroud)

sql t-sql sql-server stored-procedures sql-execution-plan

6
推荐指数
1
解决办法
341
查看次数

输出子句 VS 触发器

在我们的数据库中,大多数表都有一个dbupddate字段指示datetime最后一个INSERTUPDATE应用于该行。

为了避免该字段具有错误的值,存在触发器(有时AFTER,有时INSTEAD OF)来确保最终该值是正确的,而不是有人尝试写入该字段的任何“手动”其他值。

现在我正在执行更新语句(实际上MERGE),并且我想要一个OUTPUT包含该字段的子句。正如我在相应的 MS 文章中读到的,OUTPUT忽略触发器。

是否有任何解决方法可以返回触发器后的OUTPUT值?dbupddate我不想进行另一个查询来绘制信息,因为我不能保证在这些查询之间的瞬间,另一个用户的第三个查询可能不会改变所有内容。


遵循 Larnu 的建议后的结果

我运行了提供的示例,唯一的例外是将字段default的值更改updatetime为,convert(datetime2,'1900-01-01')以便我可能有意义。我运行了 4 个查询中的每一个,然后从各自的表中进行选择并比较了值updatetime

INSERT INTO dbo.Sample1 (Someint)
OUTPUT inserted.*
INTO @inserted
SELECT 1;

SELECT 'Sample1 INSERT',*
FROM @inserted; -- 1900-01-01 00:00:00.000000
select * from Sample1  -- 2018-11-05 13:12:13.141580
Run Code Online (Sandbox Code Playgroud)

我猜这里的输出会忽略触发器并返回after触发器生效之前插入的默认值。

DECLARE @inserted table (ID int, Someint int, …
Run Code Online (Sandbox Code Playgroud)

sql t-sql sql-server output-clause database-trigger

5
推荐指数
1
解决办法
3225
查看次数

日期时间函数:学期、季度

我在选择查询上使用这些公式,基于 [Date] 字段。1-6月为1个学期,7-12月为2个学期。季度是 3 个月的版本(1 月至 3 月等为 1 个月)。

case when Month([Date])>=7 then 2 else 1 end as [Semester],
ceiling((Month([Date])-1)/3)+1 as [Quarter]
Run Code Online (Sandbox Code Playgroud)

这些工作,但我想知道是否有一个更简单/更优雅的解决方案(尽管我已经检查了日期时间功能)。

我觉得奇怪的是,带有 ntile() 函数的语言在日期方面没有类似的东西。

sql t-sql sql-server datetime

2
推荐指数
1
解决办法
7347
查看次数

如何使用 TRANSACTION 将 CREATE TRIGGER 放入 TRY-CATCH 块中?

我不是 SQL 的高级程序员,也许我的问题很愚蠢,但我还没有在谷歌中找到答案。我们有一些 SQL 结构来实现更改包:

...
BEGIN TRY
    BEGIN TRANSACTION;
    <User Code Is Here>
    ...
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ...
END CATCH;
...
Run Code Online (Sandbox Code Playgroud)

如何放置 CREATE TRIGGER 块链而不是<User Code Is Here>没有错误:

-- Table1
CREATE TRIGGER trTable1_Dates ON dbo.Table1
AFTER INSERT, UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   ...
   SET NOCOUNT OFF;
END
GO
...
-- TableN
CREATE TRIGGER trTableN_Dates ON dbo.TableN
AFTER INSERT, UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   ...
   SET NOCOUNT OFF;
END
GO
Run Code Online (Sandbox Code Playgroud)

目的是创建所有触发器或不创建任何触发器,并在失败时在 CATCH 代码块中打印消息。 …

t-sql sql-server transactions try-catch database-trigger

2
推荐指数
1
解决办法
330
查看次数

SELECT 上如何可能出现死锁

我正在游标内运行一个过程。经过多次成功的迭代,我得到了这个: Transaction (Process ID 104) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

我不会发布完整的详细信息,因此我不期望得到细粒度的调试答案。事实:

  1. 我确信没有其他人(包括我在另一个会话中)使用该过程,因为我正在开发它并且
  2. 该事务在执行时“卡住” select(我看到来自 dm exec 请求的正在运行的查询)

如果我的两点没记错的话,是否有可能陷入僵局?死锁是否会要求资源的所有相关用户都对其进行写入操作,这会在资源请求图中创建一个循环?我理解 a 中的超时错误select,但无法理解死锁。我缺少什么?


更新:

我放弃了进一步的调试,因为我注意到我认为存在的索引并不存在。创建时,性能还可以。

然而,为了保持这个有用并希望能找到答案,以下是我调查的更多内容、一些事实和对评论的想法:

首先,sql server版本是2008。我知道这是不支持的。我无法提出建议,更不用说更新服务器了。

我发现 Jeroen Mostert 的评论很有趣。“过去”有多少?我注意到在 sys.dm_os_waiting_tasks 中,会话被自身阻塞多次,且等待类型为 CXPACKET。我做了一些搜索,但选项(maxdop 1)没有解决问题。但是,请记住不存在的索引将导致性能糟糕。难道是附加了正确的并行性,但是操作太多了?尽管如此,我也目睹了巨大的 dm_exec_requests.wait_time。因此,即使查询很糟糕,我还是相信周围存在奇怪的(死)锁。

如果答案/评论提出了跟踪问题的特定查询/步骤,我将很乐意重新创建它。

t-sql sql-server database-deadlocks

2
推荐指数
1
解决办法
4213
查看次数

只显示只包含 [a-z0-9] 的行

我有一个 varchar 列,它应该只包含字母和数字,而不能包含其他字符,例如;: , @ 等等

我认为这会起作用,但它不起作用:

select * from table
where field NOT LIKE '[a-z0-9]'
Run Code Online (Sandbox Code Playgroud)

regex t-sql sql-server

1
推荐指数
1
解决办法
50
查看次数

如何准备 while(@@rowcount&gt;0)

我正在使用sql服务器。

我有一段这样的代码

while(@@rowcount>0)
begin
--do stuff
end
Run Code Online (Sandbox Code Playgroud)

问题是,我想做一些整洁的事情,以确保第一次迭代能够运行。你建议在前面放什么?目前,我已经使用了

select 'Calling this to initialize @@rowcount to 1' 
Run Code Online (Sandbox Code Playgroud)

这是不言自明的,但如果有更好的东西,我想知道。

t-sql sql-server while-loop

0
推荐指数
1
解决办法
7423
查看次数