2010-02-20 4 views
1

ceci est ma troisième question ici, jusqu'à présent d'excellentes réponses ^^champ autoincrement « violation de clé » dans ClientDataSet [Delphi]

Je vais avoir aucun problème dans la navigation, la modification des données, mais insertions ...

Voici mon doute: dans un finance/logiciel stock j'ai un formulaire pour créer un nouvel ordre,
i naturellement besoin d'insérer une nouvelle ligne dans t_orders tableau
et insérer des éléments dans t_orderitems tableau avec orderId champ lié à une ligne dans t_orders

CREATE TABLE `t_orders` (
    `orderId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `clientId` INT(10) UNSIGNED NOT NULL, 
    ...) 

CREATE TABLE `t_orderitems` (
    `orderitemId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `orderId` INT(10) UNSIGNED NOT NULL, 
    ...) 

--> INDEXES AND FOREIGN KEYS OMITTED <-- 

Comment puis-je ajouter itemorders à une grille et enfin le bouton "FinalizeOrder" cliquez

  • Créer un ordre t_orders
  • Insérer des éléments dans t_orderitems associés à cet ordre

La connexion est établie à l'aide d'ADO.

Je ne sais pas si c'est possible de faire comme ça, dans ce cas, comment je devrais faire?

modifier: J'essayé d'utiliser ClientDataSets imbriqués et cela fonctionne dans certaines régions, mais je ne sais toujours pas comment obtenir l'ID de commande inséré

Edit2:
Maintenant, j'ai un autre problème, je peux N'ajoutez pas plus d'un élément dans ClientDataSet.
Étant donné que OrderItemId est vide pour tous les éléments (je ne peux obtenir ces valeurs lors de l'insertion de la base de données), lorsque j'essaie d'ajouter un deuxième élément, il me donne la clé Violation, des idées?

Si je mets UpdateMode à quelque chose de différent que upWhereKeyOnly et définissez pfInKey sur False cela fonctionne, mais je ne pense pas que ce soit une option

Toutes les idées?

Merci d'avance!
Arthur.

+0

Quelle base de données utilisez-vous? MySQL? – RRUZ

+0

Oui, mais je vais passer à PosgreSql sur la version finale – arthurprs

+1

Vérifiez la fonction mysql LAST_INSERT_ID(), voir ce lien http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html – RRUZ

Répondre

1

Je suppose que vous avez un ensemble de données ADO qui obtient des données de votre base de données et est lié à la grille? Ce que vous devez faire est une couche intermédiaire.

Créez un TClientDataset et connectez-le à votre ensemble de données ADO, puis connectez la grille à l'ensemble de données client. Quand une nouvelle commande arrive, appelez Append sur l'ensemble de données client et insérez les données pour la nouvelle commande. Cela le fera apparaître sur la grille. Lorsque vous souhaitez enregistrer vos modifications dans la base de données, appelez .Update sur l'ensemble de données client. Il utilisera l'ensemble de données ADO auquel il est lié pour envoyer les mises à jour à la base de données. Consultez la documentation sur TClientDataset pour obtenir des explications sur la façon de tout configurer; C'est l'une des rares choses dans les versions récentes qui est vraiment bien documentée.

Pour mettre à jour plusieurs tables, consultez la documentation sur les relations maître/détail et utilisez deux ensembles de données de ce type, liés les uns aux autres.

+0

Merci pour la réponse. Ce que j'essaie de faire ici est recommandé? Et comment puis-je définir les éléments orderId? – arthurprs

+0

Je ne suis pas sûr. Je n'ai aucune expérience avec les champs AUTO_INCREMENT. –

0

grâce RRUZ, ce n'est pas exactement ce que je voulais (je dois encore régler manuellement tous les OrderItems OrderId de la main avant l'insertion), mais le faire

with DataModule1.ADOQuery1 do 
begin 
    SQL.Text := 'SELECT LAST_INSERT_ID()'; 
    Open(); 
    First(); 
    LastInsertId := Fields[0].Value; 
    Close(); 
end; 
1

Si vous faites une relation maître-détail entre les deux ensembles de données dans votre application, ADO peut le gérer automatiquement. Cela signifie qu'une fois que vous insérez un nouvel enregistrement dans l'ensemble de données maître, vous pouvez insérer de nouveaux enregistrements dans votre dataset (order_items) sans avoir besoin de spécifier order_id, car order_id pour l'enregistrement en cours dans l'ensemble de données maître sera automatiquement récupéré. inséré dans les enregistrements nouvellement insérés de l'ensemble de données détaillées. Pour établir une relation maître/détails entre vos jeux de données, si vous utilisez AdoTable pour un jeu de données détaillé, vous pouvez définir sa source principale sur une source de données connectée à votre jeu de données maître et définir la relation entre les deux jeux de données. Si vous utilisez AdoDataset ou AdoQuery, vous devez définir la propriété DataSource dans un ensemble de données détaillé sur une source de données connectée à votre ensemble de données maître. Vous devez ensuite ajouter une clause WHERE dans l'instruction SQL de votre jeu de données détaillé à l'aide d'un paramètre SQL portant le même nom que votre champ clé dans l'ensemble de données maître. Dans votre cas, ce serait quelque chose comme ceci:

SELECT * FROM t_orderitems WHERE OrderID = :OrderID 

vous pouvez maintenant définir votre relation dans la propriété MasterFields de votre ensemble de données détail. Étant donné que vos commandes peuvent contenir plusieurs éléments, vous pouvez définir LockType sur ltBatchOptimistic dans le jeu de données detail (order_items), de sorte qu'une fois que vous insérez un nouvel élément, il n'est pas immédiatement envoyé à la base de données. Utiliser ltBatchOptimistic signifie que vos modifications seront enregistrées dans la mémoire du client temporairement jusqu'à ce que vous appeliez la méthode UpdateBatch. UpdateBatch envoie toutes les modifications à la base de données.

Si vous souhaitez annuler la commande, vous devez appeler la méthode CancelBatch pour annuler les modifications effectuées sur l'ensemble de données détail et supprimer manuellement l'enregistrement de commande créé dans l'ensemble de données maître.

+0

Je l'ai fait, mais quand je ne peux pas ajouter plusieurs ** Articles ** dans le ** Ordre **, je reçois "violation de clé" parce que 2 égal OrderItemId – arthurprs

+0

Si le champ est défini comme AutoInc dans votre tableau, alors votre base de données est responsable de fournir une valeur pour le champ OrderItemID, pas vous. Vous ne devez pas transmettre de valeur pour ce champ à votre base de données. BTW, comment insérez-vous des éléments? utilisez-vous les méthodes TDateset (par exemple, Insert, Append), ou écrivez-vous manuellement l'instruction Insert SQL? – vcldeveloper

+0

J'ajoute à ClientDataSet en utilisant append et j'ai quitté le champ OrderItemId vide (c'est le problème car le ClientDataSet n'autorise pas 2 ClientOrderId égaux) – arthurprs

Questions connexes