这似乎是一个有很多神话和相互冲突的领域。
那么SQL Server中的表变量和本地临时表有什么区别呢?
我经常需要从结果集中的每个组中选择一些行。
例如,我可能想列出每个客户最近的“n”个最高或最低订单值。
在更复杂的情况下,要列出的行数可能因组而异(由分组/父记录的属性定义)。这部分绝对是可选的/为了额外的学分,而不是为了劝阻人们回答。
在 SQL Server 2005 及更高版本中解决这些类型问题的主要选项是什么?每种方法的主要优点和缺点是什么?
AdventureWorks 示例(为清晰起见,可选)
TransactionHistory,每个产品以从 M 到 R 的字母开头。n每个产品都有历史记录行,其中n是DaysToManufactureProduct 属性的五倍。TransactionDate, .tie-break on TransactionID.我正在尝试使用MERGE语句从表中插入或删除行,但我只想对这些行的一个子集进行操作。的文档MERGE有一个措辞非常强烈的警告:
仅指定目标表中用于匹配目的的列很重要。也就是说,指定目标表中与源表的相应列进行比较的列。不要试图通过在 ON 子句中过滤掉目标表中的行来提高查询性能,例如通过指定 AND NOT target_table.column_x = value。这样做可能会返回意外和不正确的结果。
但这正是我必须做的事情才能完成我的MERGE工作。
我拥有的数据是一个标准的项目到类别的多对多连接表(例如,哪些项目包含在哪些类别中),如下所示:
CategoryId ItemId
========== ======
1 1
1 2
1 3
2 1
2 3
3 5
3 6
4 5
Run Code Online (Sandbox Code Playgroud)
我需要做的是用新的项目列表有效地替换特定类别中的所有行。我最初的尝试是这样的:
MERGE INTO CategoryItem AS TARGET
USING (
SELECT ItemId FROM SomeExternalDataSource WHERE CategoryId = 2
) AS SOURCE
ON SOURCE.ItemId = TARGET.ItemId AND TARGET.CategoryId = 2
WHEN NOT MATCHED BY TARGET THEN
INSERT ( CategoryId, ItemId )
VALUES ( 2, ItemId ) …Run Code Online (Sandbox Code Playgroud) 我需要计算一个日期范围内的滚动总和。为了说明,使用AdventureWorks 示例数据库,以下假设语法将完全满足我的需要:
SELECT
TH.ProductID,
TH.TransactionDate,
TH.ActualCost,
RollingSum45 = SUM(TH.ActualCost) OVER (
PARTITION BY TH.ProductID
ORDER BY TH.TransactionDate
RANGE BETWEEN
INTERVAL 45 DAY PRECEDING
AND CURRENT ROW)
FROM Production.TransactionHistory AS TH
ORDER BY
TH.ProductID,
TH.TransactionDate,
TH.ReferenceOrderID;
Run Code Online (Sandbox Code Playgroud)
遗憾的是,RANGE窗口框架范围目前在 SQL Server 中不允许间隔。
我知道我可以使用子查询和常规(非窗口)聚合编写解决方案:
SELECT
TH.ProductID,
TH.TransactionDate,
TH.ActualCost,
RollingSum45 =
(
SELECT SUM(TH2.ActualCost)
FROM Production.TransactionHistory AS TH2
WHERE
TH2.ProductID = TH.ProductID
AND TH2.TransactionDate <= TH.TransactionDate
AND TH2.TransactionDate >= DATEADD(DAY, -45, TH.TransactionDate)
)
FROM Production.TransactionHistory AS TH
ORDER BY
TH.ProductID,
TH.TransactionDate, …Run Code Online (Sandbox Code Playgroud) performance sql-server t-sql sql-server-2012 window-functions query-performance
很多时候我在处理 SQL Server 时需要编写如下内容。
create table #table_name
(
column1 int,
column2 varchar(200)
...
)
insert into #table_name
execute some_stored_procedure;
Run Code Online (Sandbox Code Playgroud)
但是,创建一个具有作为存储过程结果的精确语法的表是一项繁琐的任务。例如,sp_helppublication的结果有 48 列!我想知道是否有任何简单的方法可以做到这一点。
谢谢。
SQL Server(特别是 2008 或 2012)CASE语句是评估所有WHEN条件还是在找到WHEN评估为真的子句后退出?如果它确实通过了整个条件集,这是否意味着最后一个条件评估为 true 会覆盖第一个评估为 true 的条件所做的事情?例如:
SELECT
CASE
WHEN 1+1 = 2 THEN'YES'
WHEN 1+1 = 3 THEN 'NO'
WHEN 1+1 = 2 THEN 'NO'
END
Run Code Online (Sandbox Code Playgroud)
结果是“YES”,即使最后一个 when 条件应该使它评估为“NO”。一旦找到第一个 TRUE 条件,它似乎就退出了。有人可以确认是否是这种情况。
所有这些都有效:
CREATE DATABASE [¯\_(?)_/¯];
GO
USE [¯\_(?)_/¯];
GO
CREATE SCHEMA [¯\_(?)_/¯];
GO
CREATE TABLE [¯\_(?)_/¯].[¯\_(?)_/¯]([¯\_(?)_/¯] NVARCHAR(20));
GO
CREATE UNIQUE CLUSTERED INDEX [¯\_(?)_/¯] ON [¯\_(?)_/¯].[¯\_(?)_/¯]([¯\_(?)_/¯]);
GO
INSERT INTO [¯\_(?)_/¯].[¯\_(?)_/¯]([¯\_(?)_/¯]) VALUES (N'[¯\_(?)_/¯]');
GO
CREATE VIEW [¯\_(?)_/¯].[vw_¯\_(?)_/¯] AS SELECT [¯\_(?)_/¯] FROM [¯\_(?)_/¯].[¯\_(?)_/¯];
GO
CREATE PROC [¯\_(?)_/¯].[sp_¯\_(?)_/¯] @Shrug NVARCHAR(20) AS SELECT [¯\_(?)_/¯] FROM [¯\_(?)_/¯].[vw_¯\_(?)_/¯] WHERE [¯\_(?)_/¯] = @Shrug;
GO
EXEC [¯\_(?)_/¯].[¯\_(?)_/¯].[sp_¯\_(?)_/¯] @Shrug = N'[¯\_(?)_/¯]';
GO
Run Code Online (Sandbox Code Playgroud)
但是您可能会看到我的意思:我不想要 @Shrug,我想要@¯\_(?)_/¯.
这些都不适用于 2008-2017 的任何版本:
CREATE PROC [¯\_(?)_/¯].[sp_¯\_(?)_/¯] @[¯\_(?)_/¯] NVARCHAR(20) AS SELECT [¯\_(?)_/¯] FROM [¯\_(?)_/¯].[vw_¯\_(?)_/¯] WHERE [¯\_(?)_/¯] …Run Code Online (Sandbox Code Playgroud) 我已经开发 T-SQL 好几年了,并且一直在深入挖掘,继续尽我所能学习语言的各个方面。我最近开始在一家新公司工作,并收到了我认为关于交易的奇怪建议。永远不要使用它们。相反,使用模拟事务的解决方法。这是来自我们的 DBA,他在一个数据库中工作,有很多事务,随后有很多阻塞。我主要工作的数据库没有遇到这个问题,我看到过去曾使用过事务。
我知道阻塞是预期的交易,因为这样做是他们的本性,如果你可以不使用它而逃脱,一定要这样做。但是我有很多情况下每个语句都必须成功执行。如果一个失败,他们都必须失败。
我总是尽可能缩小我的事务范围,总是与 SET XACT_ABORT ON 结合使用,并且总是在 TRY/CATCH 内。
例子:
CREATE SCHEMA someschema;
GO
CREATE TABLE someschema.tableA
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColA VARCHAR(10) NOT NULL
);
GO
CREATE TABLE someschema.tableB
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColB VARCHAR(10) NOT NULL
);
GO
CREATE PROCEDURE someschema.ProcedureName @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT, XACT_ABORT ON;
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
--Implement error
SELECT 1/0 …Run Code Online (Sandbox Code Playgroud) 我们需要将 SELECT 查询结果写入一个 csv 文件。如何在 SQL Server 2008 r2 中使用 T-SQL 来完成?我知道它可以在 SSIS 中完成,但由于某些原因,我们没有这个选项。
我尝试使用下面文章中建议的 proc,但是当我运行该 proc 时,SQL 抱怨无法运行在此 proc 中调用的 sys.sp_OACreate 和 sys.sp_OADestroy。
您知道我们如何打开这些组件或知道使用 T-SQL 写入文件的更好方法吗?
提前致谢。
是否可以将表值参数用作存储过程的输出参数?
这是,我想在代码中做什么
/*First I create MY type */
CREATE TYPE typ_test AS TABLE
(
id int not null
,name varchar(50) not null
,value varchar(50) not null
PRIMARY KEY (id)
)
GO
--Now I want to create stored procedu whic is going to send output type I created,
--But it looks like it is inpossible, at least in SQL2008
create PROCEDURE [dbo].sp_test
@od datetime
,@do datetime
,@poruka varchar(Max) output
,@iznos money output
,@racun_stavke dbo.typ_test READONLY --Can I Change READONLY with OUTPUT …Run Code Online (Sandbox Code Playgroud) t-sql ×10
sql-server ×8
parameter ×2
case ×1
datatypes ×1
merge ×1
performance ×1
transaction ×1
unicode ×1