Alv*_*Lin 1 database delphi sqlite database-locking
我面临两个问题......
(1)当我尝试使用Delphi XE6写入数据库(SQLite)时,我总是得到数据库被锁定的错误消息.我确信每次使用FDConnection1.Close命令访问数据库时都会关闭数据库.
(2)如何从传入参数中插入表格?我有以下传入参数
procedure TStock_Bookkeeping.Write_To_DB(const Stock_Code, Stock_Name,
Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee: string);
Run Code Online (Sandbox Code Playgroud)
并尝试使用以下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)';
Run Code Online (Sandbox Code Playgroud)
但它似乎不起作用......
以下是我遇到问题的完整程序
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;
Run Code Online (Sandbox Code Playgroud)
任何提示将非常感激.提前致谢.
执行动态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;
Run Code Online (Sandbox Code Playgroud)
q.SQL.Text:=
'INSERT INTO Each_Stock_Owned (Stock_Code, Stock_Name) VALUES ('+
QuotedStr(Stock_Code) + ', '+
QuotedStr(Stock_Name) + ')';
q.ExecSQL;
Run Code Online (Sandbox Code Playgroud)
差异很大.肮脏的方式会让您暴露于SQL注入问题(就像在大多数其他语言中,当您以语音方式构建SQL但没有参数时).这对您来说可能是一个问题,也可能不是问题.如果您知道该过程仅由您自己的代码私有调用,并且那些过程参数值只能包含好的值...或者如果您在构建和执行SQL之前进行了一些好的参数检查...那么您就是安全的.
但是如果使用参数(纯方式)执行此操作,则会自动保护SQL注入,因为引擎会验证SQL语句,而不知道参数值.因此,引用已知SQL语句结构,并且不能通过实际值更改.
另一个考虑因素是执行INSERT语句的频率.纯方法允许您准备查询ONCE,并使用不同的参数值执行多次(您不能销毁查询对象,也不能更改SQL属性,并且必须调用一次Prepare方法).如果你在一个循环中经常运行它,那么它比以脏方式多次构建SQL更有效.OTOH如果你只需要插入一行,它可能会带来更多的开销.
=================
旁白...... CL是对的......这些值不应该是字符串.请记住,Parameter对象具有许多属性来处理不同的数据类型:
q.ParamsByName('somedate').AsDateTime := Date;
q.ParamsByName('somenumeric').AsFloat := 3/4;
Run Code Online (Sandbox Code Playgroud)
... 等等.
如果你不使用参数,那么事情就变得困难了.QuoteStr函数适用于字符串,但如果要直接在SQL中刻录日期和货币以及其他值类型,则必须知道自己在做什么.您可能会遇到许多不同的问题...特定于区域设置或格式设置不利于与您的服务器通信,这可能位于世界的另一端,或者可能无法读取以这种方式格式化的值.您可能必须处理特定于引擎的格式和转换问题.
如果您使用参数,那么FireDAC应该为您处理所有这些;)