Verifique se a tabela existe sem usar "selecionar de"


176

Existe uma maneira de verificar se existe uma tabela sem selecionar e verificar valores nela?

Ou seja, eu sei que posso SELECT testcol FROM testtableverificar a contagem de campos retornados, mas parece que deve haver uma maneira mais direta / elegante de fazer isso.


Visite stackoverflow.com/a/167680/12495091 para obter a resposta !!!!!!!!!
Saurabh Chopra 07/01

@SaurabhChopra Isso é para o SQL Server, isso está perguntando sobre o MySql.
Alejandro

Respostas:


323

Se você deseja estar correto, use INFORMAÇÕES_SCHEMA .

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

Como alternativa, você pode usar SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Se houver uma linha no conjunto de resultados, a tabela existe.


3
Sim, isso funciona bem e é elegante, mas ainda usa SELECT...FROMsintaxe ... Eu estava meio que procurando por algo comoEXISTS testtable
Ben

9
O jeito que Marc e eu declaramos fazer é o caminho certo. Não existe uma declaração de tipo 'existe' no MySQL. 'Existe' no MySql é uma cláusula que requer uma operação como SELECT, UPDATE ou DELETE.
doogle

@ Steve A terceira opção não é portátil.
precisa saber é o seguinte

1
@SergioTulentsev Independentemente da tag, prefiro a maneira portátil à proprietária.
precisa saber é o seguinte

1
@Filype, isso não é realmente um problema, pois ele está apenas verificando se a consulta foi bem-sucedida ou não. No caso em que a tabela não possui linhas, a consulta ainda terá êxito, apenas com um conjunto de resultados vazio.
Bill Dami 23/08/13

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

se você receber uma contagem diferente de zero, a tabela existe.


2
Eu realmente não entendo o que aconteceu aqui. Eu verifiquei as respostas, porque estou fazendo isso agora, e é verdade que a resposta de Sergio Tulentsev foi anterior (1 min) e ofereceu 3 soluções, mas essa é a mais eficaz. Por que devo selecionar algo mais ou mais o que eu quero? Eu preciso de um 1/0 "booleano" neste caso. A tabela existe ou não? Não quero limitar tudo, não quero gostar de nada, não quero erros. Essa deve ser a resposta aceita.
vaso123

1
Observe que TEMPORARY TABLEisso não está funcionando.
Thomas Lobker

27

Uma comparação de desempenho:

  • MySQL 5.0.77, em um banco de dados que possui cerca de 11.000 tabelas.
  • Selecionando uma tabela não usada recentemente, para que não seja armazenada em cache.
  • Média de mais de 10 tentativas cada. (Nota: feito com tabelas diferentes para evitar 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');

Observe que se você estiver executando muito isso - como em muitas solicitações de HTML em um curto período - o segundo será muito mais rápido, pois será armazenado em cache em média 200 ms ou mais.


16

Você pode consultar a tablesvisualização do sistema INFORMATION_SCHEMA :

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

Se nenhuma linha retornou, a tabela não existe.


9

Depois de ler todas as opções acima, prefiro a seguinte declaração:

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

Indica exatamente o que você deseja fazer e, na verdade, retorna um 'booleano'.


2
essa deve ser a resposta aceita. conciso e simples #
307 Dika

isso não retorna um booleano, retorna um conjunto de resultados. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice


7

Aqui está uma tabela que não é um SELECT * FROM

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

Entendi isso de um profissional de banco de dados, aqui está o que me disseram:

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

Mais fácil e eficiente.
e2-e4

3

Esta solução modificada acima não requer conhecimento explícito do banco de dados atual. É então mais flexível.

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

2

Apenas para adicionar uma maneira extra de fazer isso, e dependendo do que você precisar, você poderá usar um manipulador para o erro er_no_such_table : 1146 como este:

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

mostrar tabelas como 'table_name'

se isso retornar linhas> 0, a tabela existe


1

Você pode fazer algo como abaixo:

            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

Expandindo esta resposta , pode-se escrever ainda uma função que retorna TRUE / FALSE com base na existência ou não de uma tabela:

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

Este método compacto retorna 1 se existir 0 se não existir.

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

Você pode colocar em uma função 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 chame

Select ExistTable('my_table');

retornar 1 se existir 0 se não existir.


0

Eu uso isso em 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

Há vários problemas a serem observados com as respostas aqui:

1) INFORMATION_SCHEMA.TABLESfaz não incluem tabelas temporárias.

2) Usando qualquer tipo de SHOWconsulta, ou seja,SHOW TABLES LIKE 'test_table' , forçará o retorno de um conjunto de resultados ao cliente, o que é um comportamento indesejável para verificar se existe uma tabela no lado do servidor, de dentro de um procedimento armazenado que também retorna um conjunto de resultados.

3) Como alguns usuários mencionaram, você deve ter cuidado com o uso SELECT 1 FROM test_table LIMIT 1 .

Se você fizer algo como:

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

Você não obterá o resultado esperado se a tabela tiver zero linhas.

Abaixo está um procedimento armazenado que funcionará para todas as tabelas (mesmo TEMPORARY).

Pode ser usado como:

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;

O código:

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

Este foi o meu procedimento EXISTS 'go-to' que verifica as tabelas temporárias e normais. Este procedimento funciona no MySQL versão 5.6 e superior. O parâmetro @DEBUG é opcional. O esquema padrão é assumido, mas pode ser concatenado para a tabela na instrução @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 ;

Aqui está o exemplo de instrução de chamada com @debug on:

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

A variável @tblExists retorna um booleano.


-1

Nenhuma das opções, exceto SELECT, não permite o nome do banco de dados conforme usado no SELECT, então escrevi isso:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.