小编Hei*_*nzi的帖子

SQL Server 2019 执行无法访问的代码

[更新:此问题描述了SQL Server 2019 累积更新 5 中已修复的错误。]


考虑以下重现示例(fiddle):

CREATE FUNCTION dbo.Repro (@myYear int)
RETURNS datetime
AS
BEGIN
    IF @myYear <> 1990
    BEGIN
        RETURN NULL
    END

    DECLARE @firstOfYear datetime;
    SET @firstOfYear = DATEFROMPARTS(@myYear, 1, 1);
    
    IF DATEDIFF(day, @firstOfYear, @firstOfYear) <> 0
    BEGIN
        RETURN NULL
    END

    RETURN @firstOfYear
END
SELECT dbo.Repro(0);
Run Code Online (Sandbox Code Playgroud)

显然,如果输入是 ,该函数应该返回 1990 年 1 月的第一天1990NULL否则返回。是的,我知道这DATEDIFF(day, @firstOfYear, @firstOfYear) <> 0是一个荒谬的操作。这是一个演示潜在错误的mcve,而不是生产代码。

现在让我们SELECT dbo.Repro(0)在 SQL Server 2017 和 SQL Server …

sql-server functions sql-server-2019

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

为什么建议将 BLOB 存储在单独的 SQL Server 表中?

这个备受好评的 SO 答案建议将图像放在单独的表中,即使与另一个表只有 1:1 的关系:

如果您决定将图片放入 SQL Server 表中,我强烈建议使用单独的表来存储这些图片——不要将员工照片存储在员工表中——将它们保存在单独的表中。这样,Employee 表可以保持简洁和高效,假设您并不总是需要选择员工照片作为查询的一部分。

为什么?我的印象是SQL Server 只在表中存储一个指向某些专用 BLOB 数据结构的指针,那么为什么要手动创建另一个间接层呢?它真的能显着提高性能吗?如果是,为什么?

sql-server blob

32
推荐指数
3
解决办法
2万
查看次数

为什么 ANSI SQL 将 SUM(无行)定义为 NULL?

ANSI SQL标准定义(第6.5章,集功能规范),用于空的结果集的集合函数以下行为:

COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL
Run Code Online (Sandbox Code Playgroud)

为 AVG、MIN 和 MAX 返回 NULL 非常有意义,因为空集的平均值、最小值和最大值是未定义的。

然而,最后一个让我感到困扰:在数学上,空集的 SUM 是明确定义的:0。使用 0,加法的中性元素,作为基本情况使一切保持一致:

SUM({})        = 0    = 0
SUM({5})       = 5    = 0 + 5
SUM({5, 3})    = 8    = 0 + 5 + 3
SUM({5, NULL}) = NULL = 0 + 5 + NULL
Run Code Online (Sandbox Code Playgroud)

定义SUM({})null基本上使“无行”成为不适合其他行的特殊情况:

SUM({})     = NULL  = NULL
SUM({5})    = 5    != …
Run Code Online (Sandbox Code Playgroud)

null aggregate relational-theory sql-standard

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

SQL Server 将 A &lt;&gt; B 拆分为 A &lt; B OR A &gt; B,如果 B 是不确定的,则会产生奇怪的结果

我们在 SQL Server 中遇到了一个有趣的问题。考虑以下重现示例:

CREATE TABLE #test (s_guid uniqueidentifier PRIMARY KEY);
INSERT INTO #test (s_guid) VALUES ('7E28EFF8-A80A-45E4-BFE0-C13989D69618');

SELECT s_guid FROM #test
WHERE s_guid = '7E28EFF8-A80A-45E4-BFE0-C13989D69618'
  AND s_guid <> NEWID();

DROP TABLE #test;
Run Code Online (Sandbox Code Playgroud)

小提琴

请暂时忘记s_guid <> NEWID()条件似乎完全无用 - 这只是一个最小的重现示例。由于NEWID()匹配某个给定常量的概率极小,因此每次都应评估为 TRUE。

但事实并非如此。运行此查询通常会返回 1 行,但有时(非常频繁,超过 10 次中的 1 次)返回 0 行。我已经在我的系统上使用 SQL Server 2008 复制了它,您可以使用上面链接的小提琴 (SQL Server 2014) 在线复制它。

查看执行计划显示查询分析器显然将条件拆分为s_guid < NEWID() OR s_guid > NEWID()

查询计划截图

...这完全解释了为什么它有时会失败(如果第一个生成的 ID 小于给定的 ID,而第二个生成的 ID 大于给定的 ID)。 …

sql-server optimization

26
推荐指数
3
解决办法
1383
查看次数

如何取消 SQL Server 中的应用锁定请求?

sp_getapplock存储过程有以下返回值:

0:同步成功授予锁。
1:等待其他不兼容的锁释放后,成功授予锁。
-1:锁定请求超时。
-2:锁定请求被取消。
-3:锁定请求被选为死锁牺牲品。
-999:表示参数验证或其他调用错误。

我正在编写一个用于调用sp_getapplock我们的数据访问层的包装器,我想知道在什么情况下可以返回 -2,以便我可以抛出一个描述性和有用的异常。-1 和 -3 的返回值的含义很明显,我可以轻松创建导致返回这些值的测试条件。我将如何设法获得 -2 的返回值?

sql-server locking

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

SQL Server 的崩溃恢复能力可以提高吗?

我们有运行 SQL Server(2008 SP4 和 2016 SP1)的 PC,它们经常断电。显然,这有时会导致 SQL Server 数据库的(索引)损坏,我们需要稍后恢复。

我知道 SQL Server 不是为这种情况设计的,正确的解决方案是修复断电的原因(如果您好奇,请在下面详细介绍)。尽管如此,我可以设置 SQL Server 中的任何调整选项来降低断电时数据库损坏的风险吗?


背景:“PC”是安装在叉车上的 Windows 平板电脑。当用户关闭叉车时,平板电脑就会断电。我们曾尝试教用户在关闭叉车之前正确关闭 Windows,但失败了(可能是因为在大多数情况下只是将其关闭“有效”)。我们目前还在研究其他选项,例如添加一个 UPS,它会在断电时向平板电脑发出信号关闭。

sql-server crash

20
推荐指数
3
解决办法
3245
查看次数

我如何找出*为什么*用户具有某些有效权限?

我知道我可以使用sys.fn_my_permissions以下方法查询有效权限:

USE myDatabase;
SELECT * FROM fn_my_permissions('dbo.myTable', 'OBJECT') 

 entity_name | subentity_name | permission_name 
------------------------------------------------
 dbo.myTable |                | SELECT          
 dbo.myTable |                | UPDATE          
 ...
Run Code Online (Sandbox Code Playgroud)

这告诉我当前用户myTable在数据库中是否具有 SELECT、INSERT、UPDATE 等权限myDatabase

是否可以很容易地找出为什么用户拥有这些权限?例如,我希望有一个fn_my_permissions_ex输出附加reason列的函数:

USE myDatabase;
SELECT * FROM fn_my_permissions_ex('dbo.myTable', 'OBJECT') 

 entity_name | subentity_name | permission_name | reason
------------------------------------------------------------------------------------------------------------------------------------
 dbo.myTable |                | SELECT          | granted to database role public
 dbo.myTable |                | UPDATE          | member of group MYDOMAIN\Superusers, which belongs to database role db_datawriter
 ... …
Run Code Online (Sandbox Code Playgroud)

security sql-server permissions debugging

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

不应该避免吗?

在一些 SQL Server 开发人员中,普遍认为NOT IN速度非常慢,应该重写查询,以便它们返回相同的结果,但不要使用“evil”关键字。(示例)。

这有什么道理吗?

例如,SQL Server 中是否存在一些已知错误(哪个版本?)导致使用NOT IN的查询比使用的等效查询具有更差的执行计划

  • 一个LEFT JOIN结合了NULL支票或
  • (SELECT COUNT(*) ...) = 0WHERE条款中?

performance sql-server except query-performance

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

反转可以返回 UNKNOWN 的布尔表达式

例子

我有一张桌子

ID  myField
------------
 1  someValue
 2  NULL
 3  someOtherValue
Run Code Online (Sandbox Code Playgroud)

和一个 T-SQL 布尔表达式,它可以计算为 TRUE、FALSE 或(由于 SQL 的三元逻辑)UNKNOWN:

SELECT * FROM myTable WHERE myField = 'someValue'

-- yields record 1
Run Code Online (Sandbox Code Playgroud)

如果我想获得所有其他记录,我不能简单地否定表达式

SELECT * FROM myTable WHERE NOT (myField = 'someValue')

-- yields only record 3
Run Code Online (Sandbox Code Playgroud)

我知道为什么会发生这种情况(三元逻辑),并且我知道如何解决这个特定问题。

我知道我可以使用myField = 'someValue' AND NOT myField IS NULL并且我得到一个永远不会产生 UNKNOWN 的“可逆”表达式:

SELECT * FROM myTable WHERE NOT (myField = 'someValue' AND myField IS NOT NULL)

-- yields records 2 …
Run Code Online (Sandbox Code Playgroud)

sql-server condition

11
推荐指数
2
解决办法
4041
查看次数

浮点数的非确定性总和

让我说出显而易见的拳头:我完全理解浮点类型不能准确表示十进制值。这不是关于那个!尽管如此,浮点计算应该是确定性的

既然这已经解决了,让我向您展示我今天观察到的奇怪案例。我有一个浮点值列表,我想总结一下:

CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.2), (1.2), (1.2), (3), (5);

SELECT STR(SUM(#someFloats.val), 30, 15) FROM #someFloats;

DROP TABLE #someFloats;

-- yields:
--   13.600000000000001
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好 - 这里没有惊喜。我们都知道1.2不能用二进制表示来精确表示,所以“不精确”的结果是意料之中的。

现在,当我左加入另一个表时,会发生以下奇怪的事情:

CREATE TABLE #A (a int);
INSERT INTO #A (a) VALUES (1), (2);

CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.2), (1.2), (1.2), (3), (5);

SELECT #A.a, STR(SUM(#someFloats.val), 30, 15)
  FROM #someFloats LEFT JOIN …
Run Code Online (Sandbox Code Playgroud)

sql-server floating-point

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