70 votes

Sous-requête dans l'enregistrement actif de codeigniter

SELECT * FROM certs WHERE id NOT IN (SELECT id_cer FROM revokace);

Comment écrire la déclaration de sélection ci-dessus dans le code actif de CodeIgniter?

93voto

Rocket Hazmat Points 87407

->where() prend en charge le passage de n'importe quelle chaîne et l'utilisera dans la requête.

Vous pouvez essayer d'utiliser ceci:

$this->db->select('*')->from('certs');
$this->db->where('`id` NOT IN (SELECT `id_cer` FROM `revokace`)', NULL, FALSE);

Le ,NULL,FALSE dans le where() indique à CodeIgniter de ne pas échapper la requête, ce qui pourrait la compliquer.

MISE À JOUR : Vous pouvez également consulter la bibliothèque de sous-requêtes que j'ai écrite.

$this->db->select('*')->from('certs');
$sub = $this->subquery->start_subquery('where_in');
$sub->select('id_cer')->from('revokace');
$this->subquery->end_subquery('id', FALSE);

0 votes

Les sous-requêtes dans CI ne sont toujours pas prises en charge à ce jour?

15 votes

@iMohammad: Les sous-requêtes dans CI ne seront jamais officiellement prises en charge. Toutes les bases de données ne le prennent pas en charge; CI est censé fonctionner avec n'importe quelle base de données.

48voto

user2336400 Points 151

Les fonctions _compile_select() et _reset_select() sont obsolètes.
Au lieu de cela, utilisez get_compiled_select():

#Créer la clause WHERE
$this->db->select('id_cer');
$this->db->from('revokace');
$where_clause = $this->db->get_compiled_select();

#Créer la requête principale
$this->db->select('*');
$this->db->from('certs');
$this->db->where("`id` NOT IN ($where_clause)", NULL, FALSE);

2 votes

Je préfère presque personnellement cela car je suis capable de segmenter chaque sous-requête et de les garder en toute sécurité échappées et préparées une fois compilées.

0 votes

Ils ne sont pas obsolètes dans codeigniter 2.7 qui est encore en cours d'utilisation. L'opérateur a posé cette question en 2011, ce qui est avant Codeigniter 3. Si vous utilisez Codeigniter 2.7, la réponse de @mattumotu est la bonne.

18voto

mattumotu Points 368

Les enregistrements actifs de CodeIgniter ne prennent actuellement pas en charge les sous-requêtes, cependant j'utilise l'approche suivante :

# Créer la clause where
$this->db->select('id_cer');
$this->db->from('revokace');
$where_clause = $this->db->_compile_select();
$this->db->_reset_select();

# Créer la requête principale
$this->db->select('*');
$this->db->from('certs');
$this->db->where("`id` NOT IN ($where_clause)", NULL, FALSE);

_compile_select() et _reset_select() sont deux méthodes non documentées (à ma connaissance) qui compilent la requête et renvoient le SQL (sans l'exécuter) et réinitialisent la requête.

Dans la requête principale, le FALSE dans la clause WHERE indique à CodeIgniter de ne pas échapper à la requête (ou d'ajouter des backticks, etc.), ce qui pourrait perturber la requête. (Le NULL est simplement parce que la clause WHERE a un deuxième paramètre optionnel que nous n'utilisons pas)

Cependant, vous devez savoir que étant donné que _compile_select() et _reset_select() ne sont pas des méthodes documentées, il est possible que leur fonctionnalité (ou leur existence) puisse changer dans les prochaines versions.

5 votes

$this->db->_compile_select(); est obsolète et je crois que _reset_select() l'est aussi. Cette réponse est absolue.

0 votes

@Bandpay oui malheureusement j'ai réalisé après avoir testé les requêtes.

1 votes

_compile_select() n'est pas obsolète. Pour des raisons inconnues, à partir de CI 2.1.0, c'est une fonction protégée (dans system/database/DB_active_rec.php), ce qui signifie que vous ne pouvez pas l'utiliser à moins de supprimer la clause "protected" de la déclaration de la fonction (mais soyez toujours prudent lorsque vous modifiez le cœur).

2voto

Abhijit Mazumder Points 514

Il est peut-être un peu tard pour la question initiale mais pour les futures requêtes, cela pourrait aider. La meilleure façon d'accomplir cela est d'obtenir le résultat de la requête interne dans un tableau comme ceci

$this->db->select('id');
$result = $this->db->get('votre_table');
return  $result->result_array();

Ensuite, utilisez ce tableau dans la clause record active suivante

$this->db->where_not_in('id_de_une_autre_table', 'tableau_retourné_précédemment');

J'espère que cela aidera

7 votes

Je pense que le problème avec cette solution est qu'elle nécessite deux appels à la base de données, alors qu'une sous-requête n'en nécessite qu'un seul.

0 votes

Je suis d'accord. Mais je trouve cela beaucoup plus lisible. S'il n'y a pas de répercussions significatives sur les performances en raison de la requête supplémentaire lancée, je préférerais cette approche plutôt que d'écrire une sous-requête qui pourrait comporter ses propres pièges

0 votes

Je n'utiliserais pas cela dans l'un de mes projets. Il est inutile de faire 2 allers-retours vers la base de données lorsque le travail peut être accompli en un seul. Cette technique ne devrait pas être promue aux chercheurs à la recherche d'une solution élégante/professionnelle.

-2voto

Mohit Bumb Points 1378
$this->db->where('`id` IN (SELECT `someId` FROM `anotherTable` WHERE `someCondition`='condition')', NULL, FALSE);

Source : http://www.247techblog.com/use-write-sub-queries-codeigniter-active-records-condition-full-explaination/

0 votes

Cette réponse n'implémente pas entièrement les méthodes disponibles de CI pour construire une requête. Les réponses précédemment publiées donnent de meilleurs conseils que ce post. Aucune nouvelle valeur pour cette page. De plus, le lien hypertexte n'a pas chargé correctement, il s'agit donc d'une réponse uniquement basée sur le code. Aucune valeur pour cette page ou les chercheurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X