Question

Je suis confronté à deux problèmes ...

(1) Lorsque j'essaie d'écrire dans une base de données (SQLite) à l'aide de Delphi Xe6, je reçois toujours la base de données est un message d'erreur verrouillé.Je suis certain que je ferme la base de données à chaque fois que j'y accède en utilisant la commande Fdconnection1.close;

(2) Comment puis-je insérer dans une table des paramètres entrants? J'ai les paramètres entrants suivants

procedure TStock_Bookkeeping.Write_To_DB(const Stock_Code, Stock_Name,
Tran_Date, Buy_Sell, Price_Per_Share, Num_Shares, Trans_Fee: string);

et essayé d'écrire dans la table avec la commande SQL suivante:

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)';

Mais il ne semble pas fonctionner ...

Ce qui suit est la procédure complète dont j'ai des problèmes avec

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;

Toute astuce sera très appréciée.Merci d'avance.

Était-ce utile?

La solution

Il existe deux techniques pour exécuter une instruction SQL dynamique. Mais je vais utiliser un SQL plus court, pour vous concentrer sur la logique:

la voie pure (en utilisant des paramètres)

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;

la voie sale (bâtiment SQL)

q.SQL.Text:=
  'INSERT INTO Each_Stock_Owned (Stock_Code, Stock_Name) VALUES ('+
  QuotedStr(Stock_Code) + ', '+
  QuotedStr(Stock_Name) + ')';
q.ExecSQL;

Les différences sont significatives. La solution sale vous expose à des problèmes d'injection SQL (comme dans la plupart des autres langues, lorsque vous construisez SQL Dinamiquement, mais sans paramètres). Cela pourrait être ou ne pas être un problème pour vous. Si vous savez que la procédure est appelée de manière privée par votre propre code et que ces valeurs de paramètre de procédure ne peuvent contenir que de bonnes valeurs ... ou si vous faites un bon paramètre vérifiant avant de construire et d'exécuter votre SQL ... alors vous êtes en sécurité .

Mais si vous le faites avec des paramètres (la voie pure), vous êtes automatiquement protégé de l'injection SQL, car l'instruction SQL est validée par le moteur, sans connaître les valeurs de paramètre. La structure de l'instruction SQL est donc connue par le moteur et ne peut pas être modifiée par les valeurs réelles.

Une autre considération est la fréquence, vous allez exécuter cette déclaration d'insertion. La voie pure vous permet de préparer la requête une fois et de l'exécuter plusieurs fois avec différentes valeurs de paramètres (vous ne devez pas détruire l'objet de requête, ni changer la propriété SQL, et vous devez appeler la méthode de préparation une fois). Si vous l'exécutez fréquemment dans une boucle, il peut être plus efficace que la construction de SQL plusieurs fois la solution sale. OTOH Si vous avez juste besoin d'insérer une seule ligne, elle peut poser un peu plus de frais généraux.

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

En tant que de côté ... CL a raison ... Ces valeurs ne devraient pas être des chaînes. N'oubliez pas que l'objet de paramètre a de nombreuses propriétés pour gérer différents types de données:

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

... et ainsi de suite.

Si vous n'utilisez pas de paramètres, les choses deviennent difficiles. La fonction de traitement est bonne pour les chaînes, mais si vous souhaitez graver des dates et des monnaies et d'autres types de valeur directement dans votre SQL, vous devez savoir ce que vous faites. Vous pouvez rencontrer de nombreux problèmes différents ... paramètres de format spécifiques ou formats qui ne sont pas utiles à la combinaison avec votre serveur, qui peut être à l'extrémité opposée du monde, ou peut simplement ne pas être en mesure de lire des valeurs formatées de cette façon. Vous devrez peut-être gérer les problèmes de formatage et de conversion spécifiques du moteur.

Si vous utilisez des paramètres, Tiredac devrait alors prendre soin de tout cela pour vous;)

Autres conseils

Pour obtenir des valeurs dans la requête, utilisez les paramètres (il est expliqué le documentation ):

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;

(et je doute que toutes ces valeurs soient vraiment des chaînes ...)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top