web-dev-qa-db-fra.com

Comment vérifier si des noms de table spécifiques existent dans une base de données?

Tout ce que je veux, c'est vérifier si un tableau existe ou non et je ne peux pas le comprendre.

J'ai essayé:

for ($r = 0; $r < count($tableArray); $r++) {
    $db = JFactory::getDbo();
    $query = $db->getQuery(true);
    $query = "select * from `#__".$tableArray[$r]."` LIMIT 1";
    $db->setQuery($query);

    if ($db->setQuery($query) !== False) {
        $results = $db->loadAssocList();
        echo "<br>".$tableArray[$r]."table found";
    } else {
        echo "<br>".$tableArray[$r]."table NOT found";
    }
}

J'ai également essayé d'obtenir un tableau de noms de tables Joomla que je peux parcourir.

Array('table1','table2','table3' etc

Je peux le faire avec SHOW TABLES, Mais cela produit un grand tableau de tableaux, chacun avec une entrée.


Solution que j'ai utilisée:

J'inclus ce que j'ai fait à la fin; les deux réponses ont été utiles.

J'ai fait ceci pour obtenir le tableau des tables:

$db = JFactory::getDbo();
$results = $db->setQuery('SHOW TABLES')->loadColumn();

et puis j’ai utilisé in_array() pour savoir si la table que je cherchais était là:

$prefix = $db->getPrefix();
for ($r = 0; $r < count($tableArray); $r++) {
    if (in_array($prefix.$tableArray[$r], $results)) {
        echo "<br>Found ".$tableArray[$r];
    }else{
        echo "<br>Missing ".$tableArray[$r];
    }
}

$tableArray Est le tableau contenant les noms de table à vérifier.

1
user1616338

Lorsque vous utilisez SHOW TABLES, Chargez les résultats avec loadColumn() pour recevoir un tableau simple avec les noms de table comme valeurs.

print_r(JFactory::getDbo()->setQuery('SHOW TABLES')->loadColumn());

Sortie:

Array
(
    [0] => tbl_assets
    [1] => tbl_associations
    [2] => tbl_banner_clients
    [3] => tbl_banner_tracks
    [4] => tbl_banners
...
)
1
Sharky

Ce qui risque de vous faire trébucher, c'est que votre $tableArray N'a pas de préfixe. Cela est évident dans votre requête car vous ajoutez le nom du fichier avec le préfixe #__ Dans la clause FROM. Le jeu de résultats fournira le préfixe rendu avec le nom du fichier, de sorte que les valeurs du tableau en entrée ne correspondent pas aux valeurs du jeu de résultats.

* Important: essayez toujours d’éviter les requêtes itératives sur la base de données en guise de meilleure pratique. Si vous exécutez plusieurs requêtes inutilement, le chargement de pages sera lent, sans parler de la charge de votre système.

J'ai testé les éléments suivants pour réussir sur mon localhost. J'ai écrit ceci pour être complètement dynamique (pas de codage en dur du nom de la base de données ou du préfixe de la table).

Si vous ne souhaitez pas filtrer les noms de table dans le jeu de résultats, vous pouvez utiliser ceci:

$db = JFactory::getDbo();
$results = $db->setQuery('SHOW TABLES')->loadColumn();

$prefix = $db->getPrefix();
foreach ($tableArray as $t) {
    echo "<br>" , (in_array($prefix.$t, $results) ? "Found " : "Missing ") , $t;
}

Sinon, vous pouvez filtrer le jeu de résultats en étendant la logique de requête.

Code:

$tableArray = ["banners", "content", "cucumbers"];
try {
    $db = JFactory::getDbo();
    $config = JFactory::getConfig();
    $dbname = $config->get('db');
    $prefix = $db->getPrefix();
    foreach ($tableArray as $t) {
        $q_tablenames[] = $db->q($prefix.$t);  // prefix and quote-wrap for the query
    }
    $query = $db->getQuery(true)
        ->select("SUBSTRING(table_name, 7)")
        ->from("information_schema.tables")
        ->where(["table_schema = " . $db->q($dbname), "table_name IN (" . implode(',', $q_tablenames) . ")"]);
    // echo $query->dump();    // never show to public
    $db->setQuery($query);
    $found = $db->loadColumn();
    foreach ($tableArray as $tablename) {
        echo "<div>$tablename table " , (in_array($tablename, $found) ? "" : "not ") , "found</div>";
    }
} catch (Exception $e) {
    JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');    // never show actual error to public
}

Sortie:

banners table found
content table found
cucumbers table not found

La raison pour laquelle j'utilise une requête plus détaillée est parce que je n'ai pas réellement besoin d'extraire tous nom de la table de la base de données - je n'ai besoin que de celles qui existent dans le tableau. Il s’agit davantage d’intentions de codage directes plutôt que de la micro-optimisation (que je ne prendrai pas la peine de comparer).

Les données IN sont préfixées car les valeurs $tableArray Ne sont pas pré-équipées de préfixes. Le SELECT élimine les préfixes pour les comparaisons simples dans la boucle foreach().


Voici une approche alternative utilisant SHOW TABLES Qui donne le même résultat:

$tableArray = ["banners", "content", "cucumbers"];
try {
    $db = JFactory::getDbo();
    $config = JFactory::getConfig();
    $dbname = $config->get('db');
    $prefix = $db->getPrefix();
    foreach ($tableArray as $t) {
        $q_tablenames[] = $db->q($prefix . $t);  // prefix and quote-wrap for the query
    }
    $db->setQuery("SHOW TABLES FROM " . $db->qn($dbname) . " WHERE " . $db->qn("Tables_in_$dbname") . " IN (" . implode(',', $q_tablenames) . ")");
    $found = $db->loadColumn();
    foreach ($tableArray as $tablename) {
        echo "<div>$tablename table " , (in_array($prefix.$tablename, $found) ? "" : "not ") , "found</div>";
    }
} catch (Exception $e) {
    JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');    // never show to public
}
3
mickmackusa