根据此博客,函数或存储过程的参数如果不是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 成为参数有关?我的 SQL Server 版本是 SQL Server 2019 (RTM-CU18)。以下重现代码要求创建内存中文件组。对于后续操作的任何人,请记住,内存中的文件组一旦创建就无法从数据库中删除。
我有一个简单的内存表,在其中插入 1 - 1200 之间的整数:
DROP TABLE IF EXISTS [dbo].[InMem];
CREATE TABLE [dbo].[InMem] (
i [int] NOT NULL,
CONSTRAINT [PK_InMem] PRIMARY KEY NONCLUSTERED (i ASC)
) WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_ONLY );
INSERT INTO [dbo].[InMem]
SELECT TOP (1200) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
Run Code Online (Sandbox Code Playgroud)
我还有以下本机编译的存储过程:
GO
CREATE OR ALTER PROCEDURE p1
WITH NATIVE_COMPILATION, SCHEMABINDING
AS
BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL …
Run Code Online (Sandbox Code Playgroud) sql-server stored-procedures memory-optimized-tables table-valued-parameters
我有一个存储过程 (SS2k8),其中包含一些有时为 null 或为空的表值参数。我已经看到这个StackOverflow 帖子说空/空 TVP 应该简单地从调用参数列表中省略。我的问题是我无法弄清楚如何在存储过程中检查空或空值,因为“IF (@tvp IS NULL)”在过程创建时失败,并显示消息“必须声明标量变量“@tvp””。我是否必须在 TVP 上执行 SELECT COUNT(*) 并检查零?
代码摘录:
CREATE PROCEDURE [foo] (@tvp [TvpType] READONLY) AS
IF (@tvp IS NOT NULL) -- doesn't work
BEGIN
-- lots of expensive processing
END
ELSE
BEGIN
-- a little bit of cheap processing
END
...
Run Code Online (Sandbox Code Playgroud) sql-server-2008 null sql-server t-sql table-valued-parameters
我正在 SQL Server 2019 CU14 上进行测试。考虑针对兼容级别为 130 或 140 的 SQL Server 数据库创建的以下表值函数:
-- requires database compat 130 or 140 to see the issue
CREATE OR ALTER FUNCTION [dbo].[TVF_BUG_REPRO_2] (@O DateTime, @Z varchar(50))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
SELECT
CAST(
CASE
WHEN SZ.Zone1 > '' THEN (@O at time zone SZ.Zone1) at time zone 'Pacific Standard Time'
WHEN LEN(@Z) > 3 THEN (@O at time zone @Z) at time zone 'Pacific Standard Time'
ELSE @O
END AS DATETIME
) …
Run Code Online (Sandbox Code Playgroud) SqlDbType.Structured
将数据发送到 sproc 中的 Table 参数时,类型的行数\总大小是否有上限?
我找不到任何建议,所以我假设如果发送了一个巨大的数据集,只会有一个超时。
我正在查看 2000 行,所以没什么可怕的。我只是想抢占任何潜在的爆炸。
是否有针对 TVP 中使用的表类型的最佳实践或策略?例如,鉴于以下情况:
CREATE TABLE dbo.Colors (
Id int identity PRIMARY KEY,
Name nvarchar(100),
);
CREATE TABLE dbo.Shapes (
Id int identity PRIMARY KEY,
Name nvarchar(100),
);
CREATE TABLE dbo.Materials (
Id int identity PRIMARY KEY,
Name nvarchar(100),
);
CREATE TABLE dbo.Items (
Id int identity PRIMARY KEY,
Name nvarchar(100),
ColorId int FOREIGN KEY REFERENCES dbo.Colors (ID),
ShapeId int FOREIGN KEY REFERENCES dbo.Shapes (ID),
MaterialId int FOREIGN KEY REFERENCES dbo.Materials (ID),
);
Run Code Online (Sandbox Code Playgroud)
如果您实现了一个存储过程来搜索需要支持通过 TVP 选择多种颜色、多种形状和多种材料的项目(想想 UI 中的复选框列表),您会创建三种单独的表格类型,一种用于每个 TVP,还是创建一个类型以在所有三个中使用它?
换句话说,这:
CREATE …
Run Code Online (Sandbox Code Playgroud) 我正在改变function
:
ALTER FUNCTION [dbo].[fn_CalculateListing](@Listing TypeListingDatePrice READONLY)
RETURNS TypePreviousListingResult
AS
BEGIN
DECLARE @tbl_ListingDateDetails TypePreviousListingResult
RETURN @tbl_ListingDateDetails
END
GO
Run Code Online (Sandbox Code Playgroud)
但抛出错误为:
Msg 137, Level 16, State 1, Procedure fn_CalculateListing, Line 6
Must declare the scalar variable "@tbl_ListingDateDetails".
Run Code Online (Sandbox Code Playgroud)
即使我在使用该变量之前已经声明过,为什么会出现错误并要求声明?
TypePreviousListingResult 是创建为 的表类型CREATE TYPE TypePreviousListingResult AS TABLE...
。
sql-server sql-server-2012 functions user-defined-table-type table-valued-parameters
我看过很多关于如何创建表值参数的教程 - 但是如何在创建表值参数后查看它?
我更喜欢在 SSMS 中使用 GUI 的方法,但 T-SQL 也足够了。
我在一个新职位上,被告知要实现一个存储过程,该过程将接受用户 ID 列表并更新一个标志。
当我建议使用表值参数(数组模拟)时,我被告知要实现如下所示,因为这是以前的做法。我不是 DBA,但我是一名全栈开发人员,这对我来说很有趣。
仅供参考 - 用户 ID 实现为类型 int
CREATE PROCEDURE [dbo].[UpdateUsers]
@rgIDs varbinary(max) -- contains several ids
AS
DECLARE @tblTmp TABLE (ID int PRIMARY KEY)
DECLARE @ich int, @cch int, @ID int
SET @cch = DATALENGTH (@rgIDs)
SET @ich = 1
WHILE (@ich < @cch)
BEGIN
SET @ID = SUBSTRING (@rgIDs, @ich, 4)
UPDATE dbo.Users u
SET isUpdated = 1
WHERE u.ID = @ID
SET @ich = @ich + 4
END
Run Code Online (Sandbox Code Playgroud)
不是表值类型在这里工作得更好吗?更具可读性、性能、更不容易出错等......?
我相信我将使用 SQL Server 2012 或 …
我在 SQL 中创建了一个表类型:
CREATE TYPE [dbo].[MyObject_TableType] AS TABLE
(
[Name] VARCHAR(MAX) DEFAULT '',
[Index] VARCHAR(MAX) DEFAULT ''
)
Run Code Online (Sandbox Code Playgroud)
我构建了一个DataTable
并用一个填充它DataRow
。我将该表作为参数提供给存储过程:
// Set up connection and command variables (code omitted)
// ...
// Make the data table
var table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Index");
// Add one row that is missing an Index
var row = table.NewRow();
row["Name"] = "ObjectOne";
table.Rows.Add(row);
// Make a parameter for the table
var tableParameter = new SqlParameter("MyObjects", SqlDbType.Structured)
{
TypeName = "MyObject_TableType", …
Run Code Online (Sandbox Code Playgroud) sql-server default-value c# user-defined-table-type table-valued-parameters