Controlla se la tabella esiste senza usare "seleziona da"


176

C'è un modo per verificare se esiste una tabella senza selezionare e controllare i valori da essa?

Cioè, so che posso andare a SELECT testcol FROM testtablecontrollare il conteggio dei campi restituiti, ma sembra che ci debba essere un modo più diretto / elegante per farlo.


Visita stackoverflow.com/a/167680/12495091 per la risposta !!!!!!!!!
Saurabh Chopra

@SaurabhChopra Questo è per SQL Server, questo è chiedere a MySql.
Alejandro,

Risposte:


323

Se vuoi essere corretto, utilizza INFORMATION_SCHEMA .

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

In alternativa, puoi usare SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Se esiste una riga nel set di risultati, esiste una tabella.


3
Sì, funziona bene ed è elegante, ma usa ancora la SELECT...FROMsintassi ... Stavo cercando qualcosa di simileEXISTS testtable
Ben

9
Il modo in cui Marc ed io abbiamo dichiarato di farlo è il modo corretto. Non esiste un'istruzione di tipo "esiste" MySql. "Esiste" in MySql è una clausola che richiede un'operazione come SELEZIONA, AGGIORNA o ELIMINA.
doogle,

@Steve La terza opzione non è portatile.
ta.speot.è il

1
@SergioTulentsev Indipendentemente dal tag, preferisco il modo portatile al modo proprietario.
ta.speot.è il

1
@Filype questo non è davvero un problema, poiché sta solo verificando se la query ha avuto esito positivo o meno. Nel caso in cui la tabella non abbia righe, la query avrà comunque esito positivo, solo con un set di risultati vuoto.
Bill Dami,

66
SELECT count(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA = 'your_db_name') AND (TABLE_NAME = 'name_of_table')

se si ottiene un conteggio diverso da zero, la tabella esiste.


2
Davvero non capisco cosa sia successo qui. Ho controllato le risposte, perché lo sto facendo ora, ed è vero che la risposta di Sergio Tulentsev era precedente (1 minuto) e offriva 3 soluzioni, ma questa è la più efficace. Perché dovrei selezionare qualcosa di più o qualcos'altro che voglio? Ho bisogno di un 1/0 "booleano" in questo caso. La tabella esiste o no? Non voglio limitare tutto, non voglio piacere niente, non voglio errori. Questa dovrebbe essere la risposta accettata.
vaso123

1
Si noti che su TEMPORARY TABLEquesto non funziona.
Thomas Lobker,

27

Un confronto delle prestazioni:

  • MySQL 5.0.77, su un db che ha circa 11.000 tabelle.
  • Selezione di una tabella utilizzata non di recente in modo che non sia memorizzata nella cache.
  • Media di oltre 10 tentativi ciascuno. (Nota: fatto con tabelle diverse per evitare la memorizzazione nella cache).

322ms: show tables like 'table201608';

691ms: select 1 from table201608 limit 1;

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

Nota che se stai eseguendo molto, come su molte richieste HTML in un breve periodo, il secondo sarà molto più veloce poiché verrà memorizzato nella cache mediamente 200 ms o più velocemente.


16

È possibile eseguire una query sulla tablesvista del sistema INFORMATION_SCHEMA :

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

Se non viene restituita alcuna riga, la tabella non esiste.


9

Dopo aver letto tutto quanto sopra, preferisco la seguente dichiarazione:

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

Indica esattamente cosa vuoi fare e in realtà restituisce un "booleano".


2
questa dovrebbe essere la risposta accettata. conciso e semplice
Dika,

questo non restituisce un valore booleano, ma restituisce un set di risultati. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice

7

Invece di fare affidamento su errori, è possibile eseguire una query INFORMATION_SCHEMA.TABLESper verificare se la tabella esiste. Se c'è un record, esiste. Se non c'è nessun record, non esiste.


1
Ahh, ora ci stiamo avvicinando! Vado a provare.
Ben

1
@Steve: è ancora un SELECT FROM. :-)
Sergio Tulentsev,

7

Ecco una tabella che non è un SELECT * FROM

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

Ottenuto questo da un professionista del database, ecco cosa mi è stato detto:

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

Più semplice ed efficiente.
e2-e4,

3

Questa soluzione modificata dall'alto non richiede una conoscenza esplicita del database corrente. È quindi più flessibile.

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

2

Solo per aggiungere un modo in più per farlo, e in base a ciò di cui hai bisogno potresti usare un gestore per errore er_no_such_table : 1146 come questo:

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 ;

2

mostra tabelle come 'nome_tabella'

se questo restituisce righe> 0 la tabella esiste


1

Puoi fare qualcosa come di seguito:

            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!");
            }

1

Espandendo questa risposta , si potrebbe ulteriormente scrivere una funzione che restituisce VERO / FALSO in base all'esistenza o meno di una tabella:

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');

1

Questo metodo compatto restituisce 1 se esiste 0 se non esiste.

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

Puoi inserire una funzione 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 ;

e chiamalo

Select ExistTable('my_table');

restituisce 1 se esiste 0 se non esiste.


0

Lo uso in 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;
    }

0

Ci sono diversi problemi da notare con le risposte qui:

1) INFORMATION_SCHEMA.TABLESlo fa non includere le tabelle temporanee.

2) Utilizzando qualsiasi tipo di SHOWquery, ad esSHOW TABLES LIKE 'test_table' , imporrà la restituzione di un gruppo di risultati al client, che è un comportamento indesiderato per verificare se esiste una tabella sul lato server, all'interno di una procedura memorizzata che restituisce anche un gruppo di risultati.

3) Come menzionato da alcuni utenti, devi stare attento a come lo usi SELECT 1 FROM test_table LIMIT 1 .

Se fai qualcosa del tipo:

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

Non otterrai il risultato atteso se la tabella ha zero righe.

Di seguito è una procedura memorizzata che funzionerà per tutti tabelle (anche TEMPORANEO).

Può essere usato come:

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;

Il codice:

/*
    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 ;

0

Questa è stata la mia procedura EXISTS "go-to" che controlla sia le tabelle temporanee che quelle normali. Questa procedura funziona in MySQL versione 5.6 e successive. Il parametro @DEBUG è facoltativo. Si presume lo schema predefinito, ma può essere concatenato alla tabella nell'istruzione @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 ;

Ecco l'istruzione call di esempio con @debug su:

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

La variabile @tblExists restituisce un valore booleano.


-1

Nessuna delle opzioni tranne SELECT non consente il nome del database utilizzato in SELECT, quindi ho scritto questo:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.