【问题标题】:Use SQL Server table-valued parameters without creating a type on the SQL Server使用 SQL Server 表值参数而不在 SQL Server 上创建类型
【发布时间】:2021-06-28 17:00:23
【问题描述】:

我正在尝试在单个参数(表值参数)上传递多个值,并且它在示例之后工作正常

C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Database\FireDAC\Samples\DBMS Specific\MSSQL\TVP

SQL:

create type TVPType as table(Code integer, Name varchar(100), RegDate datetime, Notes varchar(max))
go

create table TVPTab(Code integer, Name varchar(100), RegDate datetime, Notes varchar(max))
go

德尔福:

procedure TForm1.btnQryManualSetupClick(Sender: TObject);
var
  oDS: TFDMemTable;
  i: Integer;
begin
  Start;

  FDQuery2.SQL.Text := 'insert into TVPTab (Code, Name, RegDate, Notes) ' +
    'select Code, Name, RegDate, Notes from :t';
  oDS := TFDMemTable.Create(nil);
  oDS.FieldDefs.Add('Code', ftInteger);
  oDS.FieldDefs.Add('Name', ftString, 100);
  oDS.FieldDefs.Add('RegDate', ftTimeStamp);
  oDS.FieldDefs.Add('Notes', ftMemo);
  FDQuery2.Params[0].DataTypeName := 'TVPType';
  FDQuery2.Params[0].AsDataSet := oDS;

  (FDQuery2.Params[0].AsDataSet as TFDMemTable).EmptyDataSet;
  for i := 1 to C_Recs do
    with FDQuery2.Params[0].AsDataSet do begin
      Append;
      Fields[0].AsInteger := i;
      Fields[1].AsString := 'str' + IntToStr(i * 10);
      Fields[2].AsDateTime := Now() + i;
      Fields[3].AsString := StringOfChar('x', 1000);
      Post;
    end;

  FDConnection1.StartTransaction;
  FDQuery2.Execute;
  FDConnection1.Commit;

  Done('TVP Qry manual setup');
end;

这段代码的问题是它迫使我在服务器上创建一个类型(在本例中为 TVPType 类型),我想使用这些表值参数而不必在服务器上创建任何对象。

可以吗?我尝试将参数定义为 ftDataset,但出现错误:找不到数据类型 READONLY。

procedure TForm1.btnQryManualSetupClick(Sender: TObject);
var
  oDS: TFDMemTable;
  i: Integer;
begin
  Start;

  FDQuery2.SQL.Text := 'insert into TVPTab (Code, Name, RegDate, Notes) ' +
    'select Code, Name, RegDate, Notes from :t';
  oDS := TFDMemTable.Create(nil);
  oDS.FieldDefs.Add('Code', ftInteger);
  oDS.FieldDefs.Add('Name', ftString, 100);
  oDS.FieldDefs.Add('RegDate', ftTimeStamp);
  oDS.FieldDefs.Add('Notes', ftMemo);
  //FDQuery2.Params[0].DataTypeName := 'TVPType';
  FDQuery2.Params[0].DataType := ftDataset;
  FDQuery2.Params[0].AsDataSet := oDS;

  (FDQuery2.Params[0].AsDataSet as TFDMemTable).EmptyDataSet;
  for i := 1 to C_Recs do
    with FDQuery2.Params[0].AsDataSet do begin
      Append;
      Fields[0].AsInteger := i;
      Fields[1].AsString := 'str' + IntToStr(i * 10);
      Fields[2].AsDateTime := Now() + i;
      Fields[3].AsString := StringOfChar('x', 1000);
      Post;
    end;

  FDConnection1.StartTransaction;
  FDQuery2.Execute;
  FDConnection1.Commit;

  Done('TVP Qry manual setup');
end;

【问题讨论】:

  • 如果您尝试执行批量插入,您可以查看this
  • 没有表类型的其他选项是 XML 和 JSON。
  • 简单的插入,C#中也有SqlBulkCopy,不知道Delphi中的等价物是什么

标签: sql-server delphi sql-server-2017 firedac delphi-10.4-sydney


【解决方案1】:

没有。如果您的多个值只是一行,您可以考虑将它们作为逗号分隔的字符串传递,然后使用 STRING_SPLIT 函数,或者使用临时表或永久表来存储多行值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    相关资源
    最近更新 更多