我面临两个问题...

(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);
.

并尝试使用以下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注入问题(如在大多数其他语言中,当您在没有参数时构建SQL时)。这可能是或不是对你有问题。如果您知道该过程仅由您自己的代码私下调用,那些过程参数值只能包含良好的值......或者如果您在构建和执行SQL之前进行一些优点的参数检查...那么您是安全的。

但是如果您使用参数(纯粹方式),您将自动保护从SQL注入保护,因为引擎验证了SQL语句,而不知道参数值。因此,引擎已知SQL语句结构,无法通过实际值更改。

另一个考虑因素是您将频率执行该插入语句。纯粹方式允许您准备一次查询,并使用不同的参数值多次执行它(不得销毁查询对象,也不会更改SQL属性,您必须调用一次准备方法)。如果您经常在循环中运行它,那么它可能比肮脏的方式大量构建SQL更有效。 OTOH如果您只需要插入一行,它可能会姿势更多的开销。

=================

作为一边...... Cl是对的......这些值不应该是字符串。请记住,参数对象有许多属性来处理不同的数据类型:

  q.ParamsByName('somedate').AsDateTime := Date;
  q.ParamsByName('somenumeric').AsFloat := 3/4;
.

......等等。

如果您不使用参数,那么事情很难。输出功能对于字符串有益,但如果您想直接在您的SQL中直接刻录日期和货币和其他值类型,则必须知道您正在执行的操作。您可能会遇到许多不同的问题......语言环境特定或格式设置不利于与服务器进行复杂,这可能位于世界的另一端,或者可能无法读取以这种方式格式化的值。您可能必须处理引擎特定的格式和转换问题。

如果您确实使用参数,则Firedac应该为您提供所有这些;)

其他提示

要将值获取查询,请使用参数(将解释文档):

query.SQL.Text := 'INSERT INTO Each_Stock_Owned'+
                    '(Stock_Code, Stock_Name, Tran_Date, Buy_Sell, '+
                     'Price_Per_Share, Num_Shares, Trans_Fee) '+
                    'VALUES (:sc, :sn, :td, :bs, :pps, :ns, :tf)';
query.ParamByName('sc').AsString := Stock_Code;
query.ParamByName('sn').AsString := Stock_Name;
query.ParamByName('td').AsString := Tran_Date;
query.ParamByName('bs').AsString := Buy_Sell;
query.ParamByName('pps').AsString := Price_Per_Share;
query.ParamByName('ns').AsString := Num_Shares;
query.ParamByName('tf').AsString := Trans_Fee;
query.ExecSQL;
.

(我怀疑所有这些值都应该是字符串...)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top