SQL Server / Delphi:如何使用表变量类型将整数列表作为参数传输?
Posted
技术标签:
【中文标题】SQL Server / Delphi:如何使用表变量类型将整数列表作为参数传输?【英文标题】:SQL Server / Delphi : how to transfer a list of integers as a parameter using a table variable type? 【发布时间】:2018-04-27 14:30:00 【问题描述】:我正在使用带有 FireDAC 组件的 DELPHI XE6,并且有一个 SQL Server 数据库服务器。
在数据库中,我有一个存储过程,它接受两个参数,一个整数,然后是一个表变量,它只接受一列整数类型。
表变量可以包含从零到多个整数。
程序的负责人:
/*
Declare @Temp dbo.LIP
insert into @Temp
Values(10901), (10902), (10903), (10904), (10905), (10912)
exec [dbo].[sp_lager_PkgList] 19, @Temp
*/
ALTER PROCEDURE [dbo].[sp_lager_PkgList]
@OwnerNo INT,
@LIPVariable dbo.LIP READONLY
AS
BEGIN
注释掉的部分包含我用来检查程序是否正常工作的代码 - 确实如此。
在 Delphi 中我是这样做的:
procedure TForm1.setUpParams;
var
sLIPNo: string;
ii: Integer;
begin
try
spMain.Prepare;
spMain.Params.ParamByName('@OwnerNo').AsInteger := StrToInt(edtPOwner.Text);
with spMain.Params.ParamByName('@LIPVariable') do
begin
DataType := ftDataSet;
DataTypeName := 'dbo.LIP';//'LGlager_PkgList.@LIPVariable';
end;
fdmtblLIPNo.Active := false;
fdmtblLIPNo.Active := True;
fdmtblLIPNo.BeginBatch();
try
for sLIPNo in mmoPLIPs.Lines do
begin
fdmtblLIPNo.Append;
try
fdmtblLIPNo.FieldByName('LIPNo').AsInteger := StrToInt(sLIPNo);
fdmtblLIPNo.Post;
finally
end;
end;
finally
fdmtblLIPNo.EndBatch;
ii := spMain.Params.ParamByName('@OwnerNo').AsInteger;
mmoDebug.Lines.Add(IntToStr(ii));
end;
spMain.ParamByName('@LipVariable').AsDataSet := fdmtblLIPNo;
finally
end;
end;
当我稍后在 delphi 程序中执行此过程时,没有传递任何参数。我已检查该程序是否已执行,以便该部分正常工作。
我做错了什么?我该怎么办?
这是 dbo.LIP 的脚本,它不是直接的火箭科学..
CREATE TYPE [dbo].[LIP] AS TABLE(
[LIPNo] [int] NULL
)
【问题讨论】:
旁注:您应该不为您的存储过程使用sp_
前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_
并使用其他东西作为前缀 - 或者根本不使用前缀!
@marc_s 另一方面,至少我怀疑微软将来会在存储过程名称中使用lager
=)
@JerryDodge:同意 - 可能性非常小 - 但 sp_
也会导致额外的、不必要的过程名称查找,从而减慢速度 - 最好完全避免它!
谢谢大家,很高兴知道我已经删除了该前缀,但遗憾的是,它并没有改变我的问题。
不可能,因为它无关紧要,至少您将参数数据类型设置为 ftObject
而不是 dtDataSet
。那DataTypeName
也是错的。
【参考方案1】:
您正在寻找的是传递一个数组,(这将有助于谷歌查询)您可以将数组传递到 SQL Server 的方式是通过用户定义的表类型。
这是一个入门:https://msdn.microsoft.com/en-us/library/bb386954(v=vs.100).aspx
这很接近:
/*
Declare @Temp dbo.LIP
insert into @Temp
Values(10901), (10902), (10903), (10904), (10905), (10912)
exec [dbo].[sp_lager_PkgList] 19, @Temp
*/
ALTER PROCEDURE [dbo].[sp_lager_PkgList]
@OwnerNo INT,
@LIPVariable dbo.LIP READONLY
您可以发布 dbo.LIP 的 DDL 吗?
您还需要启动 Profiler 并跟踪对 usp_ 的调用,这将显示您传递给 usp_ 的内容以验证您传递的内容,然后您将知道您的 SQL 或您的应用代码。
从您的代码中,如果您能够在本地运行它并运行,那么很可能您没有 SQL 问题,Profiler 会为您回答问题,如果这更容易,您也可以使用 fiddler .
匈牙利表示法通常是不好的做法,对于触发器和用户存储过程来说,这通常是常见的并且是好的做法。我建议使用 usp_ 而不是 sp_。
【讨论】:
我在问题的末尾添加了脚本。 因此,SQL 看起来不错,您需要知道传递给 SQL(Profiler 或 Fiddler)的内容。我猜这是应用程序传递/调用usp_的问题;或者我不确定您是否可以将输出传递到平面文件并发布以上是关于SQL Server / Delphi:如何使用表变量类型将整数列表作为参数传输?的主要内容,如果未能解决你的问题,请参考以下文章
delphi 如何在Delphi中执行将Excel表格里的内容导入数据库中相应表
如何使用 Delphi 7 ADOQuery.ExecSQL 在 SQL Server 上更新 DateTime,保留毫秒?
怎么在Delphi中通过BDE建立SQL Server数据库连接