J'ai une base de données avec des «livres» (histoires courtes pour les enfants) et il serait extrêmement instructif d'avoir le nombre de mots de chaque mot dans les livres.
J'ai compris comment obtenir le nombre de mots pour chaque mot en utilisant:
SELECT SUM
(
ROUND
(
(LENGTH(pageText) - LENGTH (REPLACE (pageText, "Word", "")))
/LENGTH("Word")
)
) FROM pages WHERE bookID = id;
Ce qui fonctionne à merveille pour compter les mots. MAIS cela me demande de parcourir chaque livre, de sortir chaque mot et de l'exécuter via cette fonction (je l'ai enregistré en tant que procédure stockée.)
J'ai un tableau qui contient chaque mot, sans doublons.
Ma question: existe-t-il un moyen de faire une sorte de boucle "pour chaque" sur la table Words en utilisant ma procédure stockée?
c'est à dire. passer la procédure stockée un ID de livre et un mot et enregistrer le résultat. Faire CHAQUE mot, pour CHAQUE livre. Cela me fait gagner BEAUCOUP de temps manuel ... Est-ce quelque chose que je devrais même faire du côté DB? Dois-je essayer avec PHP à la place?
Honnêtement, toute contribution est grandement appréciée!
la source
count(explode(' ', $pageText))+1
. Ou quelque chose de plus complexe pour gérer plusieurs espaces entre les mots, impliquant peut-êtrepreg_replace('/\s+/', ' ', $pageText)
1+split(/\s+/, $pageText)
. Le 1 est dû au fait que le nombre est composé d'espaces et non de mots.Réponses:
Créez une deuxième procédure qui utilise deux curseurs imbriqués.
Les curseurs des procédures stockées vous permettent de faire quelque chose de très peu semblable à SQL: parcourir un jeu de résultats une ligne à la fois, placer les valeurs de colonne sélectionnées dans des variables et faire des choses avec.
Ils sont facilement utilisés à mauvais escient, car SQL, étant déclaratif plutôt que procédural, ne devrait généralement pas avoir besoin d'opérations de type "pour chaque", mais dans ce cas, cela semble être une application valide.
Une fois que vous les maîtrisez, les curseurs sont faciles, mais ils nécessitent une approche structurée dans leur code de prise en charge qui n'est pas toujours intuitive.
J'ai récemment fourni un code "standard" assez standard pour travailler avec un curseur pour appeler une procédure stockée dans une réponse sur Stack Overflow , et j'emprunterai très fortement à partir de cette réponse, ci-dessous.
L'utilisation d'un curseur nécessite un code standard standard pour l'entourer.
Vous
SELECT
les valeurs que vous souhaitez passer, d'où que vous les obteniez (qui pourrait être une table temporaire, une table de base ou une vue, et peut inclure des appels à des fonctions stockées), puis appelez votre procédure existinf avec ces valeurs.Voici un exemple syntaxiquement valide du code nécessaire, avec des commentaires pour expliquer ce que fait chaque composant.
Cet exemple utilise 2 colonnes pour passer 2 valeurs à la procédure appelée.
Notez que les événements qui se produisent ici sont dans un ordre spécifique pour une raison. Les variables doivent être déclarées en premier, les curseurs doivent être déclarés avant leurs gestionnaires continus et les boucles doivent suivre toutes ces choses.
Vous ne pouvez pas faire les choses dans le désordre, donc lorsque vous imbriquez un curseur à l'intérieur d'un autre, vous devez réinitialiser la portée de la procédure en imbriquant du code supplémentaire à l'intérieur
BEGIN
... desEND
blocs dans le corps de la procédure; par exemple, si vous aviez besoin d'un deuxième curseur à l'intérieur de la boucle, vous le déclareriez simplement à l'intérieur de la boucle, à l'intérieur d'un autreBEGIN
...END
bloc.la source
BEGIN
/END
et sont implicitement fermés lorsqu'ils sortent de la portée ... la fermeture des curseurs n'est donc pas strictement nécessaire. En pratique, je le considère inutile et ne l'inclut pas, mais pour être complet, j'ai ajouté laCLOSE
déclaration à la réponse.