Vérifier si la table existe sans utiliser "sélectionner dans"

176

Existe-t-il un moyen de vérifier si une table existe sans en sélectionner et vérifier les valeurs?

Autrement dit, je sais que je peux aller SELECT testcol FROM testtablevérifier le nombre de champs renvoyés, mais il semble qu'il doit y avoir un moyen plus direct / élégant de le faire.

Ben
la source
Visitez stackoverflow.com/a/167680/12495091 pour la réponse !!!!!!!!!
Saurabh Chopra le
@SaurabhChopra C'est pour SQL Server, cela pose des questions sur MySql.
Alejandro le

Réponses:

323

Si vous voulez être correct, utilisez INFORMATION_SCHEMA .

SELECT * 
FROM information_schema.tables
WHERE table_schema = 'yourdb' 
    AND table_name = 'testtable'
LIMIT 1;

Vous pouvez également utiliser SHOW TABLES

SHOW TABLES LIKE 'yourtable';

S'il y a une ligne dans l'ensemble de résultats, la table existe.

Sergio Tulentsev
la source
3
Oui, cela fonctionne bien et est élégant, mais utilise toujours la SELECT...FROMsyntaxe ... Je cherchais en quelque sorte quelque chose commeEXISTS testtable
Ben
9
La façon dont Marc et moi avons dit de le faire est la bonne manière. Il n'y a pas de déclaration de type «existe» MySql. «Exists» dans MySql est une clause qui nécessite une opération telle que SELECT, UPDATE ou DELETE.
doogle
@Steve La troisième option n'est pas portable.
ta.speot.is
1
@SergioTulentsev Quelle que soit la balise, je préfère la méthode portable à la méthode propriétaire.
ta.speot.is
1
@Filype ce n'est pas vraiment un problème, car il vérifie seulement si la requête a réussi ou non. Dans le cas où la table n'a pas de lignes, la requête réussira toujours, juste avec un jeu de résultats vide.
Bill Dami
66
SELECT count(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA = 'your_db_name') AND (TABLE_NAME = 'name_of_table')

si vous obtenez un compte différent de zéro, la table existe.

Marc B
la source
2
Je ne comprends vraiment pas ce qui s'est passé ici. J'ai vérifié les réponses, car je le fais maintenant, et il est vrai que la réponse de Sergio Tulentsevs était plus tôt (1 min) et proposait 3 solutions, mais celle-ci est la plus efficace. Pourquoi devrais-je sélectionner quelque chose de plus ou autre chose que je veux? J'ai besoin d'un "booléen" 1/0 dans ce cas. La table existe-t-elle ou non. Je ne veux pas tout limiter, je ne veux rien aimer, je ne veux pas d'erreurs. Cela devrait être la réponse acceptée.
vaso123
1
Notez que sur un TEMPORARY TABLEcela ne fonctionne pas.
Thomas Lobker
27

Une comparaison des performances:

  • MySQL 5.0.77, sur une base de données contenant environ 11 000 tables.
  • Sélection d'une table non récemment utilisée pour qu'elle ne soit pas mise en cache.
  • En moyenne sur 10 essais chacun. (Remarque: fait avec différentes tables pour éviter la mise en cache).

322 ms: show tables like 'table201608';

691 ms: select 1 from table201608 limit 1;

319 ms: SELECT count(*) FROM information_schema.TABLES WHERE (TABLE_SCHEMA = 'mydb') AND (TABLE_NAME = 'table201608');

Notez que si vous l'exécutez beaucoup - comme pour de nombreuses requêtes HTML sur une courte période - la deuxième sera beaucoup plus rapide car elle sera mise en cache en moyenne 200 ms ou plus.

Ken Fricklas
la source
16

Vous pouvez interroger la tablesvue système INFORMATION_SCHEMA :

SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'databasename'
AND table_name = 'testtable';

Si aucune ligne n'est renvoyée, la table n'existe pas.

doogle
la source
9

Après avoir lu tout ce qui précède, je préfère la déclaration suivante:

SELECT EXISTS(
       SELECT * FROM information_schema.tables 
       WHERE table_schema = 'db' 
       AND table_name = 'table'
);

Il indique exactement ce que vous voulez faire et renvoie en fait un «booléen».

StationnaireVoyageur
la source
2
cela devrait être la réponse acceptée. concis et simple
Dika
cela ne renvoie pas de booléen, il renvoie un jeu de résultats. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice
7

Plutôt que de vous fier aux erreurs, vous pouvez interroger INFORMATION_SCHEMA.TABLESpour voir si la table existe. S'il y a un enregistrement, il existe. S'il n'y a pas d'enregistrement, cela n'existe pas.

ta.speot.is
la source
1
Ahh, maintenant on se rapproche! Je vais essayer.
Ben
1
@Steve: c'est toujours un SELECT FROM. :-)
Sergio Tulentsev
7

Voici une table qui n'est pas un SELECT * FROM

SHOW TABLES FROM `db` LIKE 'tablename'; //zero rows = not exist

J'ai obtenu ceci d'un pro de la base de données, voici ce qu'on m'a dit:

select 1 from `tablename`; //avoids a function call
select * from IMFORMATION_SCHEMA.tables where schema = 'db' and table = 'table' // slow. Field names not accurate
SHOW TABLES FROM `db` LIKE 'tablename'; //zero rows = not exist
csukcc
la source
Le plus simple et le plus efficace.
e2-e4
3

Cette solution modifiée par le haut ne nécessite pas de connaissance explicite de la base de données actuelle. Il est alors plus flexible.

SELECT count(*) FROM information_schema.TABLES WHERE TABLE_NAME = 'yourtable' 
AND TABLE_SCHEMA in (SELECT DATABASE());
Martin
la source
2

Juste pour ajouter un moyen supplémentaire de le faire, et en fonction de ce dont vous en avez besoin, vous pouvez utiliser un gestionnaire pour l' erreur er_no_such_table : 1146 comme ceci:

DELIMITER ;;
CREATE PROCEDURE `insert_in_my_table`(in my_var INT)
BEGIN
   -- Error number for table not found
   DECLARE CONTINUE HANDLER FOR 1146
   BEGIN
      -- table doesn't exists, do something...
      CREATE TABLE my_table(n INT);
      INSERT INTO my_table (n) values(my_var);
   END;
      -- table does exists, do something...
      INSERT INTO my_table (n) values(my_var);
END ;;
DELIMITER ;
Eracuna
la source
2

afficher des tables comme "nom_table"

si cela renvoie des lignes> 0, la table existe

Stefan
la source
1

Vous pouvez faire quelque chose comme ci-dessous:

            string strCheck = "SHOW TABLES LIKE \'tableName\'";
            cmd = new MySqlCommand(strCheck, connection);
            if (connection.State == ConnectionState.Closed)
            {
                connection.Open();
            }
            cmd.Prepare();
            var reader = cmd.ExecuteReader();
            if (reader.HasRows)
            {                             
              Console.WriteLine("Table Exist!");
            }
            else
            {                             
              Console.WriteLine("Table does not Exist!");
            }
Manish Jain
la source
1

En développant cette réponse , on pourrait en outre écrire une fonction qui renvoie TRUE / FALSE en fonction de l'existence ou non d'une table:

CREATE FUNCTION fn_table_exists(dbName VARCHAR(255), tableName VARCHAR(255))
  RETURNS BOOLEAN
  BEGIN
    DECLARE totalTablesCount INT DEFAULT (
      SELECT COUNT(*)
      FROM information_schema.TABLES
      WHERE (TABLE_SCHEMA COLLATE utf8_general_ci = dbName COLLATE utf8_general_ci)
        AND (TABLE_NAME COLLATE utf8_general_ci = tableName COLLATE utf8_general_ci)
    );
    RETURN IF(
      totalTablesCount > 0,
      TRUE,
      FALSE
    );
END
;


SELECT fn_table_exists('development', 'user');
Nae
la source
1

Cette méthode compacte renvoie 1 s'il existe 0 s'il n'existe pas.

set @ret = 0; 
SELECT 1 INTO @ret FROM information_schema.TABLES 
         WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'my_table'; 
SELECT @ret;

Vous pouvez mettre dans une fonction mysql

DELIMITER $$
CREATE FUNCTION ExistTable (_tableName varchar(255))
RETURNS tinyint(4)
SQL SECURITY INVOKER
BEGIN
  DECLARE _ret tinyint;
  SET _ret = 0;
  SELECT
    1 INTO _ret
  FROM information_schema.TABLES
  WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = _tablename LIMIT 1;
  RETURN _ret;
END
$$
DELIMITER ;

et l'appelle

Select ExistTable('my_table');

renvoie 1 s'il existe 0 s'il n'existe pas.

MCO
la source
0

J'utilise ceci en php.

private static function ifTableExists(string $database, string $table): bool
    {
        $query = DB::select("
            SELECT 
                IF( EXISTS 
                    (SELECT * FROM information_schema.COLUMNS
                        WHERE TABLE_SCHEMA = '$database'
                        AND TABLE_NAME = '$table'
                        LIMIT 1),
                1, 0)
                AS if_exists
        ");

        return $query[0]->if_exists == 1;
    }
Raza
la source
0

Il y a plusieurs problèmes à noter avec les réponses ici:

1) INFORMATION_SCHEMA.TABLESn'inclut pas les tables TEMPORAIRES.

2) L'utilisation de tout type de SHOWrequête, c'est-à-dire SHOW TABLES LIKE 'test_table', forcera le retour d'un jeu de résultats au client, ce qui est un comportement indésirable pour vérifier si une table existe côté serveur, à partir d'une procédure stockée qui renvoie également un jeu de résultats.

3) Comme certains utilisateurs l'ont mentionné, vous devez faire attention à la façon dont vous utilisez SELECT 1 FROM test_table LIMIT 1 .

Si vous faites quelque chose comme:

SET @table_exists = 0;
SET @table_exists = (SELECT 1 FROM test_table LIMIT 1);

Vous n'obtiendrez pas le résultat attendu si la table ne contient aucune ligne.

Voici une procédure stockée qui fonctionnera pour toutes les tables (même TEMPORAIRE).

Il peut être utilisé comme:

SET @test_table = 'test_table';
SET @test_db = NULL;
SET @does_table_exist = NULL;

CALL DoesTableExist(@test_table, @test_db, @does_table_exist);

SELECT @does_table_exist;

Le code:

/*
    p_table_name is required
    p_database_name is optional
        if NULL is given for p_database_name, then it defaults to the currently selected database
    p_does_table_exist
        The @variable to save the result to

    This procedure attempts to
        SELECT NULL FROM `p_database_name`.`p_table_name` LIMIT 0;

    If [SQLSTATE '42S02'] is raised, then
        SET p_does_table_exist = 0
    Else
        SET p_does_table_exist = 1

    Info on SQLSTATE '42S02' at:
        https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html#error_er_no_such_table
*/

DELIMITER $$

DROP PROCEDURE IF EXISTS DoesTableExist
$$

CREATE PROCEDURE         DoesTableExist (
    IN p_table_name VARCHAR(64),
    IN p_database_name VARCHAR(64),
    OUT p_does_table_exist TINYINT(1) UNSIGNED
)
BEGIN
    /* 793441 is used in this procedure for ensuring that user variables have unique names */

    DECLARE EXIT HANDLER FOR SQLSTATE '42S02'
    BEGIN
        SET p_does_table_exist = 0
        ;
    END
    ;


    IF p_table_name IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'DoesTableExist received NULL for p_table_name.';
    END IF;


    /* redirect resultset to a dummy variable */

    SET @test_select_sql_793441 = CONCAT(
        "SET @dummy_var_793441 = ("
            " SELECT"
                " NULL"
            " FROM ",
                IF(
                    p_database_name IS NULL,
                    "",
                    CONCAT(
                        "`",
                        REPLACE(p_database_name, "`", "``"),
                        "`."
                    )
                ),
                "`",
                REPLACE(p_table_name, "`", "``"),
                "`"
            " LIMIT 0"
        ")"
    )
    ;

    PREPARE _sql_statement FROM @test_select_sql_793441
    ;
    SET @test_select_sql_793441 = NULL
    ;
    EXECUTE _sql_statement
    ;
    DEALLOCATE PREPARE _sql_statement
    ;

    SET p_does_table_exist = 1
    ;
END
$$

DELIMITER ;
user2426679
la source
0

Cela a été ma procédure EXISTS «go-to» qui vérifie à la fois les tables temporaires et normales. Cette procédure fonctionne dans MySQL version 5.6 et supérieure. Le paramètre @DEBUG est facultatif. Le schéma par défaut est supposé, mais peut être concaténé à la table dans l'instruction @s.

drop procedure if exists `prcDoesTableExist`;
delimiter #
CREATE PROCEDURE `prcDoesTableExist`(IN pin_Table varchar(100), OUT pout_TableExists BOOL)
BEGIN
    DECLARE `boolTableExists` TINYINT(1) DEFAULT 1;
    DECLARE CONTINUE HANDLER FOR 1243, SQLSTATE VALUE '42S02' SET `boolTableExists` := 0;
        SET @s = concat('SELECT null FROM `', pin_Table, '` LIMIT 0 INTO @resultNm');
    PREPARE stmt1 FROM @s;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;
    set pout_TableExists = `boolTableExists`; -- Set output variable
    IF @DEBUG then
        select IF(`boolTableExists`
            , CONCAT('TABLE `', pin_Table, '` exists: ', pout_TableExists)
            , CONCAT('TABLE `', pin_Table, '` does not exist: ', pout_TableExists)
        ) as result;
    END IF;
END #
delimiter ;

Voici l'exemple d'instruction d'appel avec @debug activé:

set @DEBUG = true;
call prcDoesTableExist('tempTable', @tblExists);
select @tblExists as '@tblExists';

La variable @tblExists renvoie un booléen.

MAbraham1
la source
-1

Aucune des options sauf SELECT n'autorise le nom de la base de données tel qu'il est utilisé dans SELECT, j'ai donc écrit ceci:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Atis Lezdins
la source