根据此博客,函数或存储过程的参数如果不是OUTPUT
参数,则本质上是按值传递的,如果它们是参数,则基本上被视为按引用传递的更安全版本OUTPUT
。
起初我认为强制声明 TVP 的目的READONLY
是向开发人员明确表示 TVP 不能用作OUTPUT
参数,但必须有更多的进展,因为我们不能将非 TVP 声明为READONLY
. 例如以下失败:
create procedure [dbo].[test]
@a int readonly
as
select @a
Run Code Online (Sandbox Code Playgroud)
消息 346,级别 15,状态 1,过程测试
参数“@a”不能声明为 READONLY,因为它不是表值参数。
OUTPUT
出于某种原因不希望 TVP 成为参数有关?我正在重命名一些独特的约束以匹配我们的数据库对象命名约定。奇怪的是,有几个多行表值函数返回的表具有唯一约束,如下所示:
CREATE FUNCTION [dbo].[fn_name] (...)
RETURNS @Result
TABLE
(
ID BIGINT PRIMARY KEY,
...
RowNum BIGINT UNIQUE
)
BEGIN
...
RETURN
END
GO
Run Code Online (Sandbox Code Playgroud)
我尝试这样命名它,但不起作用:
CREATE FUNCTION [dbo].[fn_name] (...)
RETURNS @Result
TABLE
(
ID BIGINT PRIMARY KEY,
...
RowNum BIGINT
,CONSTRAINT UC_fn_name_RowNum UNIQUE([RowNum])
)
BEGIN
...
RETURN
END
GO
Run Code Online (Sandbox Code Playgroud)
当它是表变量函数定义的一部分时,是否可以设置唯一约束的名称?
t-sql sql-server-2012 set-returning-functions unique-constraint table-variable
对于这种特定情况,我将在下面尝试解释,使用表变量比不使用表变量性能更好。
我想知道为什么,如果可能的话,去掉表变量。
这是使用表变量的查询:
USE [BISource_UAT]
GO
set statistics io on
SET STATISTICS TIME ON
SET NOCOUNT ON;
DECLARE @OrderStartDate DATETIME = '15-feb-2015'
DECLARE @OrderEndDate DATETIME = '28-feb-2016'
DECLARE @tmp TABLE
(
strBxOrderNo VARCHAR(20)
,sintReturnId INT
)
INSERT INTO @tmp
SELECT strBxOrderNo
,sintReturnId
FROM TABLEBACKUPS.dbo.tblBReturnHistory rh
WHERE rh.sintReturnStatusId in ( 3 )
AND rh.dtmAdded >= @OrderStartDate
AND rh.dtmAdded < @OrderEndDate
SELECT
op.lngPaymentID
,op.strBxOrderNo
,op.sintPaymentTypeID
,op.strCurrencyCode
,op.strBCCurrencyCode
,op.decPaymentAmount
,op.decBCPaymentAmount
,ap.strAccountCode
,o.sintMarketID
,o.sintOrderChannelID
,o.sintOrderTypeID
,CASE WHEN opgv.lngpaymentID IS NULL THEN NULL
-- Not …
Run Code Online (Sandbox Code Playgroud) performance sql-server sql-server-2014 temporary-tables table-variable query-performance
用于预订事物的事务性数据库...
我们的供应商被要求用@tablevariables 替换#temptables(因为编译锁很重),但他们用一个实际的表来替换,该表将SPID 添加为一列,以确保存储过程只作用于适用的行。
您认为这种操作方法有什么风险吗?在所有事务都被隔离在他们自己的事务中之前......我担心我们最终可能会锁定这个表,但他们的意见是 SQL 使用行级锁定,这不会创建更多的锁。
SQL Server 版本:2016 企业版 - 13.0.5216.0
CREATE TABLE dbo.qryTransactions (
ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
spid int NOT NULL,
OrderID int,
ItemID int,
TimeTransactionStart datetime,
TimeTransactionEnd datetime,
...other fields
)
CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)
Run Code Online (Sandbox Code Playgroud) sql-server stored-procedures sql-server-2016 enterprise-edition table-variable
如果我在 master 数据库中创建了一个存储过程,并且我想从我的任何数据库中执行它,我只需点击以下链接:
这给了我这个代码示例:
只需按照上面的示例,我就可以从任何数据库调用我的过程。
如果我在 master 中创建一个表数据类型,我如何在我的任何数据库中使用它?
use master
IF NOT EXISTS (select * from sys.types where name = 'theReplicatedTables')
CREATE TYPE theReplicatedTables AS TABLE
( OBJ_ID INT NOT NULL,
PRIMARY KEY CLUSTERED (OBJ_ID)
);
use APIA_Repl_Sub
go
declare @the_tables [dbo].[theReplicatedTables]
Run Code Online (Sandbox Code Playgroud)
sql-server stored-procedures datatypes sql-server-2016 table-variable
我才发现, 通过纯粹的光彩意外的是,SQL Server 允许您创建没有任何名称的变量、参数、表变量、临时表(本地和全局)和临时存储过程(本地和全局)!好吧,至少不是我认为的名字。意思是,您可以指定DECLARE @ INT = 5;
并且这是有效的 T-SQL:它执行时没有错误,甚至没有在 SSMS 中用红色波浪线下划线标记(本问题末尾显示了完整示例列表的代码)。
鉴于数据库标识符的 MSDN 页面指出(强调我的):
有两类标识符:
常规标识符
...
分隔标识符
... 常规标识符和分隔标识符都必须包含1 到128 个字符。对于本地临时表,标识符最多可以有 116 个字符。
这当然看起来不像预期的行为,我最初认为这是一个缺陷(不会导致任何错误,但似乎不是“正确”的行为)并提交了一个连接错误:参数、变量和临时表和过程名称/标识符可以为空。
然而,同一个 MSDN 页面还指出:
常规标识符规则
变量、函数和存储过程的名称必须符合以下 Transact-SQL 标识符规则。
第一个字符必须是以下字符之一:
- Unicode 标准 3.2 定义的字母。字母的 Unicode 定义包括从 a 到 z、从 A 到 Z 的拉丁字符,以及来自其他语言的字母字符。
下划线 (_)、at 符号 (@) 或数字符号 (#)。
标识符开头的某些符号在 SQL Server 中具有特殊含义。以 at 符号开头的常规标识符始终表示局部变量或参数,不能用作任何其他类型对象的名称。以数字符号开头的标识符表示临时表或过程。以双数字符号 (##) 开头的标识符表示全局临时对象。尽管可以使用数字符号或双数字符号字符作为其他类型对象的名称的开头,但我们不推荐这种做法。
因此,可以解释为,名称的 1 个字符的最低要求(从显示“1 到 128 …
我有一个问题,如果可能的话,我可以用一些想法来解决如何在不使用(或启用)的情况下实现所需的问题xp_cmdshell
。
我知道它xp_cmdshell
本身会带来风险,即使使用代理帐户,但是 - 在我们的环境中它被禁用并且说服 IT 经理启用它充其量是困难的。
我遇到的问题是我有一个存储过程,它从各种表中查找数据并将其全部放入表变量中。
我想做以下事情:
这需要在没有任何类型的用户输入的情况下自动发生,它的电子邮件端将由同一存储过程中的变量提供。
我已经想到了两种可能做到这一点的方法,都使用 bcp 和xp_cmdshell
.
第一种方法是创建一个临时表,从表变量中选择我想要的记录到临时表中,然后使用 bcp 来触发 SSIS 包或 SQL 代理作业,它将查询临时表,导出到 CSV 和 e-给我发邮件。
第二种方法是创建一个临时表,从表变量中选择我想要的记录放入临时表中,然后使用bcp将临时表选择为CSV文件,然后使用sp_send_dbmail
发送。
第三种选择可能是触发另一个 SP/函数,并让它执行上述任一方法,从而将新功能分开 - 但这只是为了让事情变得简单。
所以,我要问的是关于如何安全地实现这一目标的任何想法,最好不使用xp_cmdshell
. 我不能使用 PowerShell 或类似的技术,因为这里没有人知道 PowerShell,虽然我熟悉 VB.NET,但是我不确定这有什么帮助(如果有的话)。
如果您需要更多信息以提供帮助,请告诉我。
我有以下过程,每天调用超过一百万次,我认为可以对其进行调整以更好地使用资源。
ALTER PROCEDURE [DenormV2].[udpProductTaxRateGet]
(
@itemNo varchar ( 20 ),
@calculateDate datetime,
@addressLine1 nvarchar( 50 ),
@addressLine2 nvarchar( 50 ),
@addressLine3 nvarchar( 50 ),
@addressLine4 nvarchar( 50 ),
@addressLine5 nvarchar( 50 ),
@addressLine6 nvarchar( 50 ),
@postalCode nvarchar( 20 ),
@countryCode varchar( 2 ),
@addressFormatID int
)
WITH EXECUTE AS 'webUserWithRW'
AS
--see Bocss2.dbo.[fnGetProductTax] for equivalent logic and comments in Bocss
DECLARE @Addresses TABLE (TaxRegionId int NOT NULL)
INSERT INTO @Addresses(TaxRegionId)
SELECT DISTINCT TaxRegionId
FROM dbo.[ShipTaxAddress]
WHERE [CountryCode] = @countryCode …
Run Code Online (Sandbox Code Playgroud) performance sql-server-2005 sql-server execution-plan table-variable query-performance
在阅读了大量有关 SQL Server 中临时表和表变量之间差异的信息后,我正在尝试从主要使用临时表切换到主要使用表变量。(它们似乎更适合我通常使用的查询类型。)
在这些查询中,表包含驱动查找过程的唯一标识符。在使用临时表时,我的习惯是包含一个PRIMARY KEY
约束,以便查询优化器知道它不会看到任何重复项。但是,鉴于优化器(在大多数情况下,对于我的查询)假定表变量仅包含单行*,根据定义这是唯一的,如果存在PRIMARY KEY
约束,查询优化器是否会做出任何不同的选择?
* 从技术上讲,它假定没有行,但将零替换为一。(因为零与估计过程的其余部分的交互非常差。)但这也取决于在编译查询时是否填充了表变量。这里有一些背景信息:SQL Server 中的临时表和表变量有什么区别?.
我目前正在使用 SQL Server 2014,但我很好奇新版本的行为是否发生变化。
正如已经指出的那样,PRIMARY KEY
约束带有聚集索引,它为查询优化器提供了更多关于如何从表变量中获取数据的选择。我意识到了这一点,并考虑了查询计划的其余部分。但是在试图澄清我的问题之后,我决定我试图提出的问题太广泛了,可能特别针对我的极端情况。(不过是对半万亿行表的导航类型查询,期望达到亚秒级性能。)所以我将保持我的问题不变。
第一个查询(插入表变量)的时间是第二个查询的两倍。它在执行计划中不使用并行性。
第二个查询(插入临时表)在其执行计划中使用并行性,并且能够在几乎一半的时间内实现结果。
我试图从表函数运行它,因此需要表变量而不是临时表。
执行计划非常复杂,我宁愿不朝那个方向深入(目前)。我想知道是否有人解释或假设为什么第一个 SQL 不使用并行性,而第二个是。
第一的:
DECLARE @TableVar as TABLE (
[Date] [date] NULL,
[B] [int] NULL,
[C] [decimal](5, 3) NULL)
INSERT INTO
@TableVar
SELECT
[Date] = CAST(LO.Dt as Date)
, [B] = DMC.[B]
, [C] = DMC.[C]
FROM
dbo.fnTblFunc1(@DateStart, @DateEnd) AS DMC
INNER JOIN dbo.fnTblFunc2(@DateStart, @DateEnd) AS LO ON DMC.Date = LO.Dt
OPTION (FORCE ORDER )
Run Code Online (Sandbox Code Playgroud)
第二:
CREATE TABLE #TempTbl(
[Date] [date] NULL,
[B] [int] NULL,
[C] [decimal](5, 3) NULL)
INSERT INTO
#TempTbl
SELECT
[Date] = CAST(LO.Dt …
Run Code Online (Sandbox Code Playgroud) 我想在表变量中存储 2 个坐标点(纬度、经度)。
我试过了:
declare @coordinates table(latitude1 decimal(12,9),
longitude1 decimal(12,9),
latitude2 decimal(12,9),
longitude2 decimal(12,9))
select latitude,
longitude into @coordinates
from loc.locations
where place_name IN ('Delhi', 'Mumbai')
select @coordinates
Run Code Online (Sandbox Code Playgroud)
它显示错误:
消息 102,级别 15,状态 1,第 2 行 '@coordinates' 附近的语法不正确。
选择查询的结果:
select latitude,
longitude
from loc.locations
where place_name IN ('Delhi', 'Mumbai')
Run Code Online (Sandbox Code Playgroud)
是:
latitude longitude
28.666670000 77.216670000
19.014410000 72.847940000
Run Code Online (Sandbox Code Playgroud)
如何将值存储在表数据类型中?
我运行了查询SELECT @@VERSION
并得到了结果:
Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (X64) 2016 年 4 月 29 日 23:23:58 版权所有 (c) Microsoft Corporation Standard …
table-variable ×11
sql-server ×10
t-sql ×3
datatypes ×2
parameter ×2
performance ×2
optimization ×1
parallelism ×1
xp-cmdshell ×1