考虑以下查询:
MERGE [Parameter] with (rowlock) AS target
USING (SELECT @AreaId, @ParameterTypeId, @Value)
AS source (AreaId, ParameterTypeId, Value)
ON (target.AreaId = source.AreaId AND
target.ParameterTypeId = source.ParameterTypeId)
WHEN MATCHED THEN
UPDATE SET target.Value = source.Value, @UpdatedId = target.Id
WHEN NOT MATCHED THEN
INSERT ([AreaId], [ParameterTypeId], [Value])
VALUES (source.AreaId, source.ParameterTypeId, source.Value);
Run Code Online (Sandbox Code Playgroud)
统计 I/O 提供以下输出:
表“参数类型”。扫描计数 0,逻辑读取 2,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表 'Area'。扫描计数 0,逻辑读取 2,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表“参数”。扫描计数 1,逻辑读取 4,物理读取 0,预读读取 0,lob 逻辑读取 …
我一直都知道UNIONSQL 中的运算符,但直到最近才发现还有其他的集合运算符,INTERSECT和EXCEPT. 我一直无法找到执行第四大集合运算符的运算符,即对称差异(例如 . 的相反INTERSECT)
看起来我可以通过使用类似的东西来获得所需的输出
SELECT Field FROM A UNION SELECT Field FROM B
EXCEPT
SELECT Field FROM A INTERSECT SELECT Field FROM B
Run Code Online (Sandbox Code Playgroud)
(假设我得到了正确的优先级),或者通过做一个反完全连接:
SELECT A.Field, B.Field
FROM A
FULL JOIN B ON B.Id = A.Id
WHERE B.Id IS NULL OR A.Id IS NULL
Run Code Online (Sandbox Code Playgroud)
但是这两个看起来都像是相当密集的查询,尤其是与其他三个基本的集合操作相比。SQL中是否存在对称差异操作而我在文档中找不到它?或者是否有一种“规范”的方式在 T-SQL 中实现它?
我有一个具有以下结构的表:
CREATE TABLE [dbo].[AUDIT_SCHEMA_VERSION](
[SCHEMA_VER_MAJOR] [int] NOT NULL,
[SCHEMA_VER_MINOR] [int] NOT NULL,
[SCHEMA_VER_SUB] [int] NOT NULL,
[SCHEMA_VER_DATE] [datetime] NOT NULL,
[SCHEMA_VER_REMARK] [varchar](250) NULL
);
Run Code Online (Sandbox Code Playgroud)
一些示例数据(似乎 sqlfiddle 有问题.. 所以放一些示例数据):
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,6,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,6,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,7,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,10,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,12,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored procedure build')
INSERT INTO [AUDIT_SCHEMA_VERSION]([SCHEMA_VER_MAJOR],[SCHEMA_VER_MINOR],[SCHEMA_VER_SUB],[SCHEMA_VER_DATE],[SCHEMA_VER_REMARK])
VALUES(1,12,13,CAST('20130405 04:41:25.000' as DATETIME),'Stored …Run Code Online (Sandbox Code Playgroud) 我知道,如果我EXISTS()调用 FK 查找值,那么,如果该 FK 约束是可信的,那么结果是立竿见影的。
如果它不受信任(比如我使用 来创建 FK 时WITH NOCHECK),那么 SQL Server 必须去检查表以查看该值是否确实存在。
使用我还有什么损失NOCHECK吗?
SQL Server 2014:
我们有一个非常大(1 亿行)的表,我们需要更新其中的几个字段。
对于日志运输等,我们显然也希望将其保持为一口大小的交易。
如果我们让下面运行一会儿,然后取消/终止查询,那么到目前为止所做的工作会全部提交,还是需要添加明确的 BEGIN TRANSACTION / END TRANSACTION 语句以便我们可以随时取消?
DECLARE @CHUNK_SIZE int
SET @CHUNK_SIZE = 10000
UPDATE TOP(@CHUNK_SIZE) [huge-table] set deleted = 0, deletedDate = '2000-01-01'
where deleted is null or deletedDate is null
WHILE @@ROWCOUNT > 0
BEGIN
UPDATE TOP(@CHUNK_SIZE) [huge-table] set deleted = 0, deletedDate = '2000-01-01'
where deleted is null or deletedDate is null
END
Run Code Online (Sandbox Code Playgroud) 我必须维护和扩展一个旧的遗留系统,其中包含不再使用的 web 服务方法和数据库表。由于我不完全确定这些表是否真的是多余的,因此我害怕删除它们。
有没有其他方法可以在不删除它们的情况下实现相同的效果(不能再使用表格)?我的想法是将它们Deleted从当前默认的dbo.
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Deleted')
BEGIN
EXEC('CREATE SCHEMA Deleted')
END
ALTER SCHEMA Deleted TRANSFER dbo.TableName;
Run Code Online (Sandbox Code Playgroud)
有没有其他选择或者模式方法有什么缺点?
我们经常会遇到“如果不存在,则插入”的情况。Dan Guzman 的博客对如何使此进程线程安全进行了出色的调查。
我有一个基本表,它只是将字符串从SEQUENCE. 在存储过程中,我需要获取该值的整数键(如果它存在),或者INSERT它然后获取结果值。该dbo.NameLookup.ItemName列有一个唯一性约束,因此数据完整性没有风险,但我不想遇到异常。
这不是一个IDENTITY所以我无法获得,SCOPE_IDENTITY并且NULL在某些情况下价值可能是。
在我的情况下,我只需要处理INSERT桌面上的安全问题,所以我试图决定是否使用MERGE这样的方法更好:
SET NOCOUNT, XACT_ABORT ON;
DECLARE @vValueId INT
DECLARE @inserted AS TABLE (Id INT NOT NULL)
MERGE
dbo.NameLookup WITH (HOLDLOCK) AS f
USING
(SELECT @vName AS val WHERE @vName IS NOT NULL AND LEN(@vName) > 0) AS new_item
ON f.ItemName= new_item.val
WHEN MATCHED THEN
UPDATE SET @vValueId = f.Id
WHEN NOT MATCHED BY TARGET THEN
INSERT …Run Code Online (Sandbox Code Playgroud) 有时我将对象名称(标识符)存储在我们的一些数据库中,例如在一些参数表中。因为我使用 '=' 或 'LIKE' 比较运算符从这些表中选择记录,所以我必须注意存储这些名称时总是带括号或不带括号。
IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = '[TABLE_NAME]';
Run Code Online (Sandbox Code Playgroud)
或者
IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = 'TABLE_NAME';
Run Code Online (Sandbox Code Playgroud)
但是,MS-SQL 有一些函数,您可以在其中使用带或不带括号的对象名称,例如 OBJECT_ID() 函数。我在dbfiddle.uk上设置了一个最小的例子。
CREATE TABLE TEST
(
ID INT IDENTITY(1,1) PRIMARY KEY,
OBJECT sysname NOT NULL
);
GO
INSERT INTO TEST VALUES ('[obj1]'),('obj2'),('obj3'),('[obj4]');
GO
Run Code Online (Sandbox Code Playgroud)
现在我可以使用 OBJECT_ID() 以这种方式检查表 TEST 是否存在:
IF OBJECT_ID('TEST') IS NOT NULL
BEGIN
SELECT 'TEST EXISTS.' OBJECT_ID;
END
GO
| OBJECT_ID |
| :----------- | …Run Code Online (Sandbox Code Playgroud) 我有一个存储过程,它基本上从一个表中选择值并将它们插入到另一个表中,这是一种归档。我想避免多人同时这样做。
当这个程序正在运行时,我不希望其他人能够启动它,但是我不希望序列化,另一个人在我完成后运行该程序。
我想要的是其他人在我运行该程序时尝试启动它以获取错误。
我尝试过使用 sp_getapplock,但是我无法完全阻止该人运行该程序。
我还尝试使用 sys.dm_exec_requests 查找过程并阻止该过程,虽然这确实有效,但我认为这不是最佳选择,因为在某些服务器上我没有运行 sys.dm_exec_sql_text(sql_handle) 的权限。
我这样做的最佳方法是什么?
我有一个简短的问题,为什么要使用use master;创建数据库?这是Microsoft 文档中的示例
USE master ;
GO
CREATE DATABASE Sales
ON
( NAME = Sales_dat,
FILENAME = 'C:\Program Files\...\saledat.mdf',
SIZE = 10,
MAXSIZE = 50,
FILEGROWTH = 5 )
LOG ON
( NAME = Sales_log,
FILENAME = 'C:\Program Files\...\salelog.ldf',
SIZE = 5MB,
MAXSIZE = 25MB,
FILEGROWTH = 5MB ) ;
Run Code Online (Sandbox Code Playgroud)