sqlite - 有没有办法使用 FireDAC 插入 Null 值作为参数?

标签 sqlite delphi firedac

当我将值插入表中时,我想将一些字段保留为空(即 Null)。我不明白为什么我想要一个字段中充满空字符串的数据库。

我使用 Delphi 10、FireDAC 和本地 SQLite DB。

编辑:提供的代码只是一个示例。在我的应用程序中,值由用户输入和函数提供,其中许多都是可选的。如果 value 为空,我想将其保留为 Null 或默认值。创建 ExecSQL 的多个变体和嵌套 If 语句也不是一个选项 - 可选字段太多(准确地说是 18 个)。

测试表:

CREATE TABLE "Clients" (
    "Name"  TEXT,
    "Notes" TEXT
);

这是我尝试的方法:

var someName,someNote: string;
begin
{...}
someName:='Vasya';
someNote:='';
FDConnection1.ExecSQL('INSERT OR REPLACE INTO Clients(Name,Notes) VALUES (:nameval,:notesval)',
    [someName, IfThen(someNote.isEmpty, Null, somenote)]);

这会引发异常:

could not convert variant of type (Null) into type (OleStr)

我尝试重载它并指定 [ftString,ftString] 但没有帮助。

目前我必须这样做,我讨厌这个凌乱的代码:

FDConnection1.ExecSQL('INSERT OR REPLACE INTO Clients(Name,Notes) VALUES ('+
    IfThen(someName.isEmpty,'NULL','"'+Sanitize(someName)+'"')+','+
    IfThen(someNote.isEmpty,'NULL','"'+Sanitize(someNote)+'"')+');');

有什么建议吗?

Edit2:目前我看到一个使用“INSERT OR REPLACE”创建新行的选项,然后对每个非空值在一行中使用多个 UPDATE。但这看起来非常无效。像这样:

FDConnection1.ExecSQL('INSERT OR REPLACE INTO Clients(Name) VALUES (:nameval)',[SomeName]);
id := FDConnection1.ExecSQLScalar('SELECT FROM Clients VALUES id WHERE Name=:nameval',[SomeName]);
if not SomeString.isEmpty then
    FDConnection1.ExecSQL('UPDATE Clients SET Notes=:noteval WHERE id=:idval)',[SomeNote,id]);

最佳答案

根据 Embarcadero 文档 ( here ):

To set the parameter value to Null, specify the parameter data type, then call the Clear method:

with FDQuery1.ParamByName('name') do begin
  DataType := ftString;
  Clear;
end;
FDQuery1.ExecSQL;

所以,我想你必须使用 FDQuery 来插入 Null 值。像这样的事情:

//Assign FDConnection1 to FDQuery1's Connection property
FDQuery1.SQL.Text := 'INSERT OR REPLACE INTO Clients(Name,Notes) VALUES (:nameval,:notesval)';
with FDQuery1.ParamByName('nameval') do
  begin
  DataType := ftString;
  Value := someName;
  end;
with FDQuery1.ParamByName('notesval') do
  begin
  DataType := ftString;
  if someNote.IsEmpty then
    Clear;
  else
    Value := someNote;
  end;
if not FDConnection1.Connected then
   FDConnection.Open;
FDQuery1.ExecSql;

以不带参数的字符串形式执行查询并不是一个好主意,因为此代码容易受到 SQL 注入(inject)攻击。

一些消息来源告诉我们这还不够,你应该这样做:

with FDQuery1.ParamByName('name') do begin
  DataType := ftString;
  AsString := '';
  Clear;
end;
FDQuery1.ExecSQL;

但我无法确认。如果主要示例不起作用,您可以尝试一下。

关于sqlite - 有没有办法使用 FireDAC 插入 Null 值作为参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62967845/

相关文章:

django - 在 Centos7 上将 SQLite3 与 Django 2.2 和 Python 3.6.7 结合使用

python - Django 内存中 SQLite3 数据库

delphi - 使用 TJSONUnMarshal 自定义注册恢复器意外失败

sql-server - FireDAC SQL Server 连接 : Untrusted certificate

android - DbAdapter 类与 ContentProvider 在 android 中有什么区别?

android - 如何在Android SQLite JOIN查询中使用保留关键字?

delphi - 我可以在 IDE 中使用 TCP/IP 运行程序并期望它们正常工作吗?

delphi - 如何获取 TDBGrid 中的列标题?

delphi - 在关闭并重新打开应用程序之前,日期格式无法正确显示

delphi - FireDac 连接问题