7
votes

Erreur de SQLite et de «contrainte» Echec »lors de la sélection et de l'insérer en même temps

Je travaille sur la fonction de migration. Il lit les données de l'ancienne table et l'insère dans le nouveau. Tout ce que ces trucs fonctionnent dans le fil d'arrière-plan avec une priorité faible.

Mes étapes dans le code pseudo. P>

sqlite> select sql from sqlite_master where tbl_name = 'tiles';
CREATE TABLE tiles('pk' INTEGER PRIMARY KEY, 'data' BLOB, 'x' INTEGER, 'y' INTEGER, 'z' INTEGER, 'importKey' INTEGER)
sqlite> select sql from sqlite_master where tbl_name = 'tiles_v2';
CREATE TABLE tiles_v2 (pk int primary key, x int, y int, z int, layer int, data blob, timestamp real)


1 commentaires

Merci pour la mise à jour. J'ai édité ma réponse et j'ai ajouté des informations plus utiles (j'espère).


6 Réponses :


10
votes

Cela signifie probablement que votre instruction insert enfreint une contrainte dans la nouvelle table. Pourrait être une contrainte de clé primaire, une contrainte unique, une contrainte de clé étrangère (si vous utilisez pragma étrangère_keys = sur; code>), etc.

Vous résolvez que soit en supprimant la contrainte , corrigeant les données ou supprimer les données. La chute de la contrainte est généralement une mauvaise chose, mais cela dépend de l'application. P>

existe une raison convaincante de copier des données une ligne à la fois au lieu d'un ensemble? P>

select pk 
from old_table_name
group by pk
having count() > 1;
  • L'ancienne table a des valeurs dupliquées dans la colonne 'pk'. li>
  • le code qui fait votre migration modifie ou injecte une valeur en double Avant d'insérer des données dans votre nouveau Tableau. Li>
  • Un autre processus, éventuellement en cours d'exécution sur un ordinateur différent, insère ou Mise à jour des données sans votre connaissance. LI>
  • Autres raisons pour lesquelles je n'ai pas encore pensé. : -) li> ul>

    Vous pouvez déterminer s'il existe des valeurs dupliquées de 'PK' dans l'ancienne table en exécutant cette requête. P>

    INSERT INTO new_table
    SELECT column_list FROM old_table;
    


6 commentaires

non. Je n'utilise pas étrangers_keys. Et il y a un autre fil qui effectue des insertions avec succès. Maintenant, je suis même rempli d'insertion toujours avec les mêmes données. et la situation n'a pas changé. Deuxième thread a toujours échoué à insérer des données. Inserts gardés par des mutiles, alors seul possible en une seule fois.


Instructions supplémentaires pour extraire le SQL DDL de SQLite. Modifiez votre question initiale et insérez les résultats de ces deux requêtes.


À l'issue, j'ai ajouté que j'essaie d'exécuter un insert avec les mêmes données dans 2 threads plusieurs fois. Premier fil (où SQLite3 * a été ouvert) fonctionne toujours bien, l'insertion dans la seconde n'a pas fonctionné. Comme vous pouvez le constater à partir des schémas de table - PK est unique dans les deux tables.


Vous pouvez isoler le problème au code d'application en exécutant Insérer dans NEW_TAble Sélectionnez Column_list à partir de Old_Table; manuellement de l'invite SQLite. Si cela réussit, le problème est dans votre code d'application; Si cela échoue, le problème est dans la base de données. Si le problème du code d'application du problème, vous devez le réduire au moindre code qui reproduit le problème, modifier votre question initiale et inclure ce code.


Merci pour votre réponse. Il y avait un bogue vraiment stupide avec la définition d'une nouvelle clé primaire.


Une bonne chose à propos de la programmation - ça vous garde humble. Moi, j'ai été humble depuis 1985.



2
votes

Juste au cas où quelqu'un atterrit ici à la recherche d'un message d'erreur "échec de la contrainte", assurez-vous que votre ID est entier , pas integer (0, 15 ) ou quelque chose.

fond

Si votre table a une colonne nommée ID , avec type integer et défini comme clé primaire, SQLite le traite comme un alias pour la colonne intégrée Rowid . Cette colonne fonctionne comme une colonne d'incrémentation automatique. Dans mon cas, cette colonne fonctionnait bien jusqu'à certains designers de table (probablement celui créé par SQLite Guys pour Visual Studio) Type de colonne modifié à partir de entier à entier (0, 15) et tout d'un coup mon application a commencé à lancer la contrainte a échoué Exception.


0 commentaires

1
votes

Juste pour le rendre plus clair: de
Assurez-vous que vous utilisez le type de données correct, j'utilisais int au lieu de integer sur la création de tables TMY comme ceci:

ID int clé principale non null

Et j'étais coincé sur le problème de contrainte sur les heures ...
Assurez-vous simplement de saisir le type de données correctement dans la création de la base de données.


0 commentaires

0
votes

L'une des raisons pour lesquelles cette erreur se produit est d'insérer également des données dupliquées pour une ligne unique. Vérifiez votre toutes les personnes uniques et toutes les clés pour des données dupliquées.


0 commentaires

2
votes

J'ai trouvé que résoudre les erreurs de contrainte de clé étrangère avec SQLite d'être gênante, en particulier sur les grands ensembles de données. Cependant, l'approche suivante contribue à identifier la relation incriminée.

  1. Désactiver la vérification de la clé étrangère: pragma étrangers_keys = 0;
  2. Exécutez la déclaration causant l'erreur - dans mon cas, il s'agissait d'un insert de 70 000 lignes avec 3 relations clés étrangères différentes.
  3. réactivez la vérification de la clé étrangère: pragma étrangère_keys = 1;
  4. Identifiez les erreurs de clé étrangère: pragma étrangère_key_check (name-nom);

    Dans mon cas, il a montré les 13 lignes avec des références non valides.


0 commentaires

0
votes

Aujourd'hui, j'ai eu une erreur similaire: La contrainte de vérification a échoué: Profil code>

J'ai d'abord lire ICI Qu'est-ce que la contrainte. P>

Les contraintes sont une intégrité qui définit certaines conditions restreindre la colonne pour contenir les données vraies lors de l'insertion ou mise à jour ou suppression de la suppression. Nous pouvons utiliser deux types de contraintes, c'est-à-dire Niveau de colonne ou contrainte de niveau de table. Les contraintes de niveau de colonne peut être appliqué uniquement sur une colonne spécifique où au niveau de la table Les contraintes peuvent être appliquées à toute la table. P> BlockQuote>

a ensuite compris que je dois vérifier comment la base de données a été créée, car j'ai utilisé SQLALCHEMY et SQLITE3 dialecte, j'ai dû vérifier les tableaux schéma code>. Schéma montrera la structure de base de données réelle. P> xxx pré>

donc ici, j'ai trouvé que la vérification booléenne est toujours 0 ou 1 et j'ai utilisé la valeur par défaut de colonne comme "Faux", donc chaque fois que j'avais Aucun forum_copy_exist ou forum_Deletted Value, False a été inséré, et parce que FALSE est une valeur non valide, elle jette une erreur et n'a pas inséré la ligne. p>

modifier par défaut de la base de données sur: p>

forum_copy_exist BOOLEAN DEFAULT '0', 
forum_deleted BOOLEAN DEFAULT '0',


5 commentaires

'FAUX' est une chaîne tandis que false est égal à 0 dans sqlite.


bool = db.column (db.boolcan, server_default = false) dans SQLalchemy est impossible à annoncer une erreur false à la colonne booléenne, seulement 0 ou 1 fonctionne


Il n'y a pas de type de données booléen dans SQLite même si vous définissez une colonne en tant que telle. SQLite considère false comme 0 et true comme 1 . Le problème que vous avez eu est une définition incorrecte des valeurs par défaut des colonnes. Lorsque vous définissez 'false' comme valeur par défaut, cela signifie que vous stockez la valeur de chaîne 'FALSE' dans la colonne lorsque vous ne fournissez pas de valeur pour cette colonne dans L'instruction insérer . Cette chaîne n'a rien à voir avec la valeur booléenne false .


Ok thx, qui a du sens, mais est impossible d'ajouter une colonne FALSE à SQLALCHYMY, si vous utilisez FALSE Python interprète en tant que valeur d'espace de noms, si vous utilisez '' false ' pour sqlite est Mauvais pour PostgreSQL est valide (non testé) également 'F' est valide pour PostgreSQL, de toute façon Safeest est bool = db.column (dB.booleran, server_default = '0') , d'après ce que j'ai testé.


Je viens de trouver comment définir true ou false correctement dans sqlalchemy de sqlalchemy.sql importer import expression et server_default = expression.false () restot maintenant je ne peux pas le tester.