有没有办法使用 FireDAC 将 NULL 值作为参数插入?
Is there a way to INSERT Null value as a parameter using FireDAC?
我想在向 table 中插入值时将某些字段留空(即 Null)。我不明白为什么我想要一个在字段中充满空字符串的数据库。
我使用 Delphi 10、FireDAC 和本地 SQLite 数据库。
编辑:提供的代码只是示例。在我的应用程序中,值由用户输入和函数提供,其中许多都是可选的。如果值为空,我想将其保留为 Null 或默认值。创建 ExecSQL 的多个变体和嵌套 If 语句也不是一个选项 - 可选字段太多(确切地说是 18 个)。
测试table:
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 注入的攻击。
有些消息来源说这还不够,您应该这样做:
with FDQuery1.ParamByName('name') do begin
DataType := ftString;
AsString := '';
Clear;
end;
FDQuery1.ExecSQL;
但我无法确认。如果主要示例不起作用,您可以尝试一下。
我想在向 table 中插入值时将某些字段留空(即 Null)。我不明白为什么我想要一个在字段中充满空字符串的数据库。
我使用 Delphi 10、FireDAC 和本地 SQLite 数据库。
编辑:提供的代码只是示例。在我的应用程序中,值由用户输入和函数提供,其中许多都是可选的。如果值为空,我想将其保留为 Null 或默认值。创建 ExecSQL 的多个变体和嵌套 If 语句也不是一个选项 - 可选字段太多(确切地说是 18 个)。
测试table:
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 注入的攻击。
有些消息来源说这还不够,您应该这样做:
with FDQuery1.ParamByName('name') do begin
DataType := ftString;
AsString := '';
Clear;
end;
FDQuery1.ExecSQL;
但我无法确认。如果主要示例不起作用,您可以尝试一下。