Salut tout le monde,
Je n'ai plus guère de temps pour intervenir ici mais je ne peux m'empêcher de lire certains fils et celui-ci appelle un bon nombre de remarques.
@ tous,
Par pitié, n'employez plus la séquence Query, Fetch*, Finalize sauf avec grandes précautions et en sachant pourquoi vous y recourrez (et en testant _tous_ les codes erreur à chaque étape).
Remplacez ça par un Exec, QuerySingleRow, GetTable ou (ce qui est préférable) GetTable2d. Ensuite testez le code erreur. Ca simplifie votre code, ça va plus vite et ça gère correctement les erreurs.
@ corrs78
Ton approche risque fort de te causer des soucis insolubles : on ne doit jamais taper dans une base SQLite depuis un réseau. La faute n'en incombe pas à SQLite (qui est d'une très grande fiabilité) mais aux protocoles existants de partage de fichiers (
aucun, sous
aucun OS, ne fonctionne correctement dans tous les cas de figure, et on est en 2012 !).
Tu peux employer
cette couche pour te mettre à l'abri de déconvenues cuisantes.
Ensuite, j'ai un souci de compréhension : tu fais tes recherches et surtout tes modifs sur une partie du nom OU du prénom. AMHA ça ne convient pas dans un cas réel simple.
Tartempion Jean-Jacques
DupontLaJoie Jacques
Avec une requête "Jacques" en modif, le résultat est douteux.
Le limit 1 est un tirage au sort, d'autant plus que SQL peut te retourner les rangs dans n'importe quel ordre, suivant l'implémentation. On n'est même pas sûrs que SQL te renvoie le même ordre dans deux SELECT identiques lancés l'un après l'autre.
Tu devrais utiliser les ID des rangs pour faire ce que tu veux et pas besoin de faire un compte avant. Qui plus est, dans un envonnement concurrentiel, ton approche amène à des situations que tu n'as pas prévu car tu n'utilises pas de transactions.
Pour ne pas bloquer la base, tu as plusieurs choix. Utiliser le mode WAL autorise concurrement UNE écriture (update, delete, ...) ET plusieurs lectures (select) sans blocage possible ni précautions particulières. Voir la doc sur le site SQLite à ce sujet. Le mode par défaut ne permet qu'une écriture OU plusieurs lectures simultanées.
Perso, je te conseille aussi de déclarer ID en INTEGER PRIMARY KEY AUTOINCREMENT (avec INTEGER en toutes lettres). Ainsi tu n'as pas besoin de faire saisir la valeur de l'ID. Ensuite, SQLite n'a pas de limitation en type et taille de contenu ; ton VARCHAR(40) équivaut à TEXT.
Tu n'as pas à "escaper" une valeur numérique (insert ou update ID), mais encore serait-il bon de s'assurer que cette valeur est numérique et n'existe pas déjà dans la base (fct ajout qui part à dame sinon). Et là aussi, transaction !
Tu devrais créer ton propre mécanisme de réservation de rangées pour qu'un poste puisse se réserver les Tartempion sans bloquer toute la base. La bonne solution passe par une table Opérations qui contient un ID d'opération en cours et une date/heure d'expiration (si un PC plante ou que l'appli reste trop longtemps "les pattes en l'air"). Tu mets l'OpId dans une colonne de ta table Utilisateurs et tu fais tes update et select en conditionnant sur l'OpId. Un trigger sur création d'une nouvelle opération fera le ménage des opérations expirées et un autre trigger répercutera l'expiration en remettant à 0 l'OpID dans la table Utilisateurs.
Maintenant côté pratique, je doute qu'un simple LIKE sur noms et prénoms fasse le boulot en exploitation. Même si tu n'as que des noms à script latin, un e ne sera jamais LIKE un é. J'ai écris une extension pour regrouper un bon nombre de fonctions Unicode, dont une recherche floue. Tu peux
télécharger librement ici.
Le chargement d'extension se fait de préférence via cette UDF :
Une autre possibilité est d'employer une table FTS3 (plutôt FTS4) pour y stocker une copie en minuscules désaccentuées des champs sur lesquels peuvent porter une recherche. FTS3/4 supporte l'extension ICU (full Unicode) mais ICU lui-même est un monstre de 18Mib plutôt lent. A toi de voir.
Dernière chose à laquelle je pense : juste après l'ouverture et la connection, lance
_SQLite_SetTimeout($hADB, 600000)
ce qui met un timeout de 10 minutes sur toute opération faite sur ta base ; en parallèle, utilise des transactions immédiates. Tu n'auras jamais de _SQLITE_BUSY ou _LOCKED.