我面临两个问题...
(1) 当我尝试使用 Delphi XE6 写入数据库 (SQLite) 时,我总是收到数据库被锁定的错误消息。我确定每次使用命令访问数据库时都会关闭数据库 FDConnection1.关闭;
(2) 如何从传入参数插入表? 我有以下传入参数
procedure TStock_Bookkeeping.Write_To_DB(const Stock_Code, Stock_Name,
Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee: string);
并尝试使用以下 SQL 命令写入表:
sSQL := 'INSERT INTO Each_Stock_Owned(Stock_Code, Stock_Name, Tran_Date, Buy_Sell,
Price_Per_Share, Num_Shares, Trans_Fee)
VALUES (Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share,
Num_Shares, Trans_Fee)';
但是好像不行...
以下是我遇到问题的完整过程
procedure TStock_Bookkeeping.Write_To_DB(const Stock_Code, Stock_Name,
Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee: string);
var
query : TFDQuery;
sSQL: string;
begin
query := TFDQuery.Create(nil);
try
ConnectToSQLite;
query.Connection := FDConnection1;
if Stock_Code.IsEmpty then
ShowMessage('Stock Code Cannot Be Empty')
else
if Stock_Name.IsEmpty then
ShowMessage('Stock Name Cannot Be Empty')
else
if Tran_Date.IsEmpty then
ShowMessage('Transaction Date Cannot Be Empty')
else
begin
// sSQL := 'INSERT INTO Each_Stock_Owned(Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee) VALUES (Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee)';
sSQL := 'INSERT INTO Each_Stock_Owned(Stock_Code, Stock_Name, Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee) VALUES (1,2,3,4,5,6,7)';
query.sql.Text := sSQL;
query.ExecSQL;
query.Open();
end;
finally
query.Close;
query.DisposeOf;
DisconnectFromSQLite;
end;
end;
任何提示将不胜感激。提前致谢。
最佳答案
执行动态 SQL 语句有两种技术。但我将使用更短的 SQL,以专注于逻辑:
纯方式(使用参数)
q.SQL.Text:=
'INSERT INTO Each_Stock_Owned (Stock_Code, Stock_Name) '+
'VALUES (:Stock_Code, :Stock_Name)';
q.Prepare; //Optional
q.ParamsByName('Stock_Code').AsString := Stock_Code;
q.ParamsByName('Stock_Name').AsString := Stock_Name;
q.ExecSQL;
肮脏的方式(构建 SQL)
q.SQL.Text:=
'INSERT INTO Each_Stock_Owned (Stock_Code, Stock_Name) VALUES ('+
QuotedStr(Stock_Code) + ', '+
QuotedStr(Stock_Name) + ')';
q.ExecSQL;
差异显着。肮脏的方式使您面临 SQL 注入(inject)问题(与大多数其他语言一样,当您动态构建 SQL 但没有参数时)。这对您来说可能是问题,也可能不是问题。如果您知道该过程仅由您自己的代码私下调用,并且那些过程参数值只能包含良好的值……或者如果您在构建和执行 SQL 之前进行了一些良好的参数检查……那么您就安全了.
但是,如果您使用参数(纯粹的方式)执行此操作,您将自动受到 SQL 注入(inject)的保护,因为引擎会验证 SQL 语句,而无需知道参数值。所以SQL语句结构是引擎已知的,不能被实际值改变。
另一个考虑因素是执行该 INSERT 语句的频率。纯粹的方式允许您准备一次查询,并使用不同的参数值执行多次(您不能破坏查询对象,也不能更改 SQL 属性,并且必须调用 Prepare 方法一次)。如果您在一个循环中频繁运行它,那么它比以肮脏的方式多次构建 SQL 更有效。 OTOH 如果您只需要插入一行,它可能会带来更多的开销。
=================
顺便说一句……CL 是对的……那些值不应该是字符串。请记住,Parameter 对象有许多属性来处理不同的数据类型:
q.ParamsByName('somedate').AsDateTime := Date;
q.ParamsByName('somenumeric').AsFloat := 3/4;
...等等。
如果不使用参数,事情就会变得困难。 QuoteStr 函数适用于字符串,但如果您想直接在 SQL 中刻录日期和货币以及其他值类型,您必须知道自己在做什么。您可能会遇到许多不同的问题...特定于区域设置或格式设置不利于与您的服务器通信,这些服务器可能位于世界的另一端,或者可能无法读取以这种方式格式化的值。您可能必须处理特定于引擎的格式和转换问题。
如果您确实使用了参数,那么 FireDAC 应该会为您处理所有这一切 ;)
关于database - Delphi:数据库被锁定(SQLite),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25052400/