考虑一下SO 上的这个答案,它使询问者对<>运营商感到放心:
<>是 ... 与 相同!=。
但随后一位评论者插嘴说:
确实,它们在功能上是相同的。但是,SQL 优化器如何使用它们是非常不同的。=/!= 被简单地评估为真/假,而 <> 意味着引擎必须查看该值是大于还是小于,这意味着更多的性能开销。只是在编写可能很昂贵的查询时需要考虑的事情。
我相信这是错误的,但为了解决潜在的怀疑论者,我想知道是否有人可以提供权威或规范的来源来证明这些运算符不仅在功能上相同,而且在所有方面都相同?
假设您有以下代码(请忽略它很糟糕):
BEGIN TRAN;
DECLARE @id int
SELECT @id = id + 1 FROM TableA;
UPDATE TableA SET id = @id; --TableA must have only one row, apparently!
COMMIT TRAN;
-- @id is returned to the client or used somewhere else
Run Code Online (Sandbox Code Playgroud)
在我看来,这不是正确管理并发性。仅仅因为您有一个事务并不意味着其他人不会读取您在获取更新语句之前所做的相同值。
现在,让代码保持原样(我意识到这作为单个语句更好地处理,甚至使用自动增量/标识列更好)有哪些确定的方法可以使其正确处理并发并防止允许两个客户端获得相同条件的竞争条件身份证价值?
我很确定将 a 添加WITH (UPDLOCK, HOLDLOCK)到 SELECT 会解决问题。该SERIALIZABLE事务隔离级别(因为它拒绝任何人阅读你做了什么,直到移植是在将似乎工作,以及UPDATE:这是假见马丁的答案)。真的吗?它们会同样有效吗?一个比另一个更受欢迎吗?
想象一下做一些比 ID 更新更合法的事情——一些基于你需要更新的读取的计算。可能涉及许多表,其中一些您会写入,而另一些则不会。这里的最佳做法是什么?
写完这个问题后,我认为锁定提示更好,因为这样你只锁定了你需要的表,但我很感激任何人的意见。
PS 不,我不知道最好的答案,真的很想得到更好的理解!:)
鉴于此表:
CREATE TABLE dbo.Target (
TargetId int identity(1, 1) NOT NULL,
Color varchar(20) NOT NULL,
Action varchar(10) NOT NULL, -- of course this should be normalized
Code int NOT NULL,
CONSTRAINT PK_Target PRIMARY KEY CLUSTERED (TargetId)
);
Run Code Online (Sandbox Code Playgroud)
在两个稍微不同的场景中,我想插入行并从标识列返回值。
INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM
(VALUES
('Blue', 'New', 1234),
('Blue', 'Cancel', 4567),
('Red', 'New', 5678)
) t (Color, Action, Code)
;
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE #Target (
Color varchar(20) NOT NULL,
Action varchar(10) NOT NULL, …Run Code Online (Sandbox Code Playgroud) 想象一下,您有两个不同的表/查询,它们应该具有/返回相同的数据。您想验证这一点。像下面的示例一样显示每个表中任何不匹配的行的简单方法是什么,比较每一列?假设表中有 30 列,其中许多是 NULLable。
当没有 PK 或每个 PK 可能有重复项时,仅加入 PK 列是不够的,并且必须使用 30 个正确处理 NULL 的连接条件进行 FULL JOIN 以及讨厌的 WHERE 条件将是一场灾难排除匹配的行。
通常,当我针对未经整理或未完全理解的数据编写新查询时,问题最严重,并且 PK 在逻辑上可用的可能性极低。我想出了两种不同的方法来解决问题,然后比较它们的结果,差异突出了我不知道的数据中的特殊情况。
结果需要如下所示:
Which Col1 Col2 Col3 ... Col30
------ ------ ------ ------ ------
TableA Cat 27 86 -- mismatch
TableB Cat 27 105 -- mismatch
TableB Cat 27 87 -- mismatch 2
TableA Cat 128 92 -- no corresponding row
TableB Lizard 83 NULL -- no corresponding row
Run Code Online (Sandbox Code Playgroud)
如果[Col1, Col2]确实是一个复合键并且我们在最终结果中按它们排序,那么我们可以很容易地看到 A 和 B 有一行不同的应该是相同的,并且每一行都有一行不在另一行中。
在上面的例子中,两次看到第一行是不可取的。
这是用于设置示例表和数据的 …
我知道您无法将值与 NULL 进行比较并期望结果而不添加类似以下代码的内容...
SELECT
*
FROM
A INNER JOIN
B ON A.ID = B.ID
WHERE
A.STRING <> B.STRING OR (A.STRING IS NULL AND B.STRING IS NOT NULL) OR (A.STRING IS NOT NULL AND B.STRING IS NULL) OR
A.DT <> B.DT OR (A.DT IS NULL AND B.DT IS NOT NULL) OR (A.DT IS NOT NULL AND B.DT IS NULL) OR
A.B <> B.B OR (A.B IS NULL AND B.B IS NOT NULL) OR (A.B IS NOT NULL AND B.B IS NULL) …Run Code Online (Sandbox Code Playgroud) I was attempting to answer the following stackoverflow question:
After posting a somewhat naive answer, I figured I'd put my money where my mouth was and actually test the scenario I was suggesting, to be sure I wasn't sending the OP off on a wild goose chase. Well, it's turned out to be much harder than I thought (no surprise there …
在 SSMS 2208 中,标识符“Lookup”被涂成粉红色,就好像它是一个函数一样(与“Power”或“Convert”颜色相同)。为什么?
您能否为中级到高级 SQL 专业人员推荐任何好的资源,以对这些资源进行彻底的研究,如果正确学习,可以更好地导航该领域的所有固有缺陷?
我正在考虑各种资源——教程、博客、手册页、PASS 会话或任何东西。
sql server 如何判断一个函数是否是确定性的?
考虑下面的函数,我认为它是确定性的(因为它最终是一个整数运算),但是当我调用它的 objectproperty 方法时,sql server 返回 0。
了解它是如何工作的将帮助我理解为什么我对这个功能的评估是错误的。
CREATE FUNCTION dbo.EndOfPreviousMonth ( @Date date )
RETURNS date
AS BEGIN
RETURN DATEADD(day, 0 - DAY(@Date), @Date);
END;
SELECT dbo.EndOfPreviousMonth('2010-01-01'); --Usage example
--Returns 0, I expected it to return 1
SELECT OBJECTPROPERTY( OBJECT_ID( 'dbo.EndOfPreviousMonth' ), 'IsDeterministic' );
Run Code Online (Sandbox Code Playgroud) 在回答有关 stackoverflow 的问题时,我提出了派生表的定义:
派生表是一个完整的查询,在括号内,就像一个真正的表一样使用。
但有评论者反对:
尽管除了“括号内”之外还有其他类型的派生表。... [例如] 视图和表值函数 ... .
并进一步支持这一点:
来自 ISO/IEC 2003 规范,框架卷的第 4.3 节,2003 年 8 月规范草案的第 13 页:“引用零个或多个基表并返回表的操作称为查询。查询的结果称为一个派生表。” 请注意,视图和表值函数都返回“查询结果”,这是一个派生表。Microsoft(以及在较小程度上,Oracle)因其在其文档中错误地将“派生表”和“子查询”等同而臭名昭著,但派生表确实也包括预定义的查询,如视图。
那么真正的独家新闻是什么?我是将我认为的派生表降级为简单的“FROM 子句别名内联子查询”还是视图没有正确派生表?
请注意:我在网上搜索了很长一段时间,但找不到任何明确的内容。我没有上述规范的副本。
此外,我认为值得解决其他问题。假设视图被正确地称为“派生表”。这是否使对视图的引用也是“派生表”或仅仅是引用?对于一个 CTE 的例子,应该把这个点带回家:
WITH SalesTotals AS (
SELECT
O.CustomerID,
SalesTotal = Sum(OrderTotal)
FROM
dbo.CustomerOrder O
GROUP BY
O.CustomerID
)
SELECT
C.Name,
S.SalesTotal
FROM
dbo.Customer C
INNER JOIN SalesTotals S
ON C.CustomerID = S.CustomerID;
Run Code Online (Sandbox Code Playgroud)
SalesTotals引入的CTEWITH是一个派生表。但INNER JOIN SalesTotals 也是派生表,还是只是对派生表的引用?这个查询有两个派生表还是一个?如果一个人,然后推而广之,我认为,一个观点可能是一个派生表,但参考它可能不具备成为一个派生表。
我有一张每天排一排的桌子,可以存放大约一百万个缓慢变化的物品。
查找这些项目Item, Date以查看它们是否存在于表中。对于涉及具有不同日期的许多项目的查找,这有点慢——我的表现在有大约 2.6 亿行。但是,能够快速插入数据以及快速查询数据对我来说很有价值。
我想将其转换为一个表格,该表格通常每个项目有一行,并带有日期范围。(如果日期范围不连续,则一个项目可能有两行。)一个原始导入文件可用于按日期显示每天的项目,与现有架构匹配。每次有新的导入文件可用时,我都会更新现有行的日期范围以涵盖新的导入数据。我还需要能够重新导入文件,以便适当更新信息。在这样的文件中,可能会添加或删除某个项目以前存在的日期。
虽然这有点烦人的任务,但我知道我可以想出正确的MERGE语句来适当地更新数据,但是需要花几个小时的时间来确保我做对了,而且可能不是一个非常快的导入过程。
所以我在玩一种有点不寻常的不同模式设计,想知道是否有人可以评论它 - 好主意,坏主意,如何使用它,性能特征,陷阱等?
Item Date
---- ----------
SLAM 2016-11-01
SLAM 2016-11-02
SLAM 2016-11-03
SLAM 2016-11-05
GULP 2016-11-01
GULP 2016-11-02
GULP 2016-11-03
GULP 2016-11-05
Run Code Online (Sandbox Code Playgroud)
(请注意,2016-11-04 到目前为止已被跳过,需要尽快加载。)
这使得插入和删除数据变得非常容易,但是,数据库增长非常快——这不是最大的表,但已经接近 8 GB,它以每月 1 GB 的速度增长(实际上有两个不同的项目不同分类系统下的代码,因此第二个项目代码的索引将使用的空间增加一倍)。此外,查询花费的时间比我想容忍的要长。
Item FromDate ToDateExclusive
---- ---------- ---------------
SLAM 2016-11-01 2016-11-04
SLAM 2016-11-05 2016-11-06
GULP 2016-11-01 2016-11-04
GULP 2016-11-05 2016-11-06
Run Code Online (Sandbox Code Playgroud)
虽然这对于空间使用和查询非常有用,但是当 2016-11-04 的新导入文件同时包含SLAM和GULP时,合并过程必须确定新日期是否连续连接到两个现有日期范围,然后更新一行以包含整个范围并删除另一行。这很棘手。
如果稍后缺少 2016-11-04 的新导入文件,则GULP必须再次将单行拆分为两行,就像上面一样。这种情况很少见,但也并非不可能,尤其是考虑到文件可能会乱序导入——它们只能按需获取——并且对多个历史文件进行更正可能会产生这种情况。
Item DateBitPattern (varbinary) …Run Code Online (Sandbox Code Playgroud) 我正在使用引用链接服务器的视图和存储过程:
SELECT Id, Name
FROM [LinkedServer].Database.dbo.FooView
Run Code Online (Sandbox Code Playgroud)
我想隐藏[LinkedServer].Database或至少隐藏[LinkedServer]我的视图和存储过程的一部分。这样我就可以拥有“与服务器无关”的代码,可以很容易地在生产服务器和开发服务器之间进行比较。
这可以在服务器级别(如链接服务器)或数据库级别(使用它的视图和存储过程)完成。
sql-server ×9
locking ×3
concurrency ×2
bulk-insert ×1
date ×1
except ×1
identity ×1
insert ×1
merge ×1
null ×1
operator ×1
performance ×1
queue ×1
sql-standard ×1
ssms ×1