Compruebe si la tabla existe sin usar "seleccionar de"


176

¿Hay alguna manera de verificar si existe una tabla sin seleccionar y verificar valores de ella?

Es decir, sé que puedo ir SELECT testcol FROM testtabley verificar el recuento de campos devueltos, pero parece que debe haber una forma más directa / elegante de hacerlo.


Visite stackoverflow.com/a/167680/12495091 para obtener la respuesta !!!!!!!!!
Saurabh Chopra

@SaurabhChopra Eso es para SQL Server, se trata de MySql.
Alejandro

Respuestas:


323

Si quiere ser correcto, use INFORMATION_SCHEMA .

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

Alternativamente, puedes usar SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Si hay una fila en el conjunto de resultados, la tabla existe.


3
Sí, eso funciona bien y es elegante, pero aún usa la SELECT...FROMsintaxis ... Estaba buscando algo así comoEXISTS testtable
Ben

9
La forma en que Marc y yo declaramos hacerlo es la forma correcta. No hay una declaración de tipo 'existe' MySql. 'Existe' en MySql es una cláusula que requiere una operación como SELECT, UPDATE o DELETE.
doogle

@Steve La tercera opción no es portátil.
ta.speot.is

1
@SergioTulentsev Independientemente de la etiqueta, prefiero la forma portátil a la forma propietaria.
ta.speot.is

1
@Filype esto no es realmente un problema, ya que solo está verificando si la consulta tuvo éxito o no. En el caso de que la tabla no tenga filas, la consulta seguirá teniendo éxito, solo con un conjunto de resultados vacío.
Bill Dami

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

Si obtiene un recuento distinto de cero, la tabla existe.


2
Realmente no entiendo lo que pasó aquí. Revisé las respuestas, porque lo estoy haciendo ahora, y es cierto que la respuesta de Sergio Tulentsevs fue anterior (1 minuto) y ofreció 3 soluciones, pero esta es la más efectiva. ¿Por qué debería seleccionar algo más o cualquier otra cosa que quiero? Necesito un "booleano" 1/0 en este caso. Es la tabla existe o no. No quiero limitar todo, no quiero que me guste nada, no quiero ningún error. Esta debería ser la respuesta aceptada.
vaso123

1
Tenga en cuenta que TEMPORARY TABLEesto no funciona.
Thomas Lobker

27

Una comparación de rendimiento:

  • MySQL 5.0.77, en una base de datos que tiene aproximadamente 11,000 tablas.
  • Seleccionar una tabla no utilizada recientemente para que no se almacene en caché.
  • Promedió más de 10 intentos cada uno. (Nota: hecho con diferentes tablas para evitar el almacenamiento en caché).

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

Tenga en cuenta que si está ejecutando esto mucho, como en muchas solicitudes HTML en un período corto, el segundo será mucho más rápido ya que se almacenará en caché un promedio de 200 ms o más rápido.


16

Puede consultar la tablesvista del sistema INFORMATION_SCHEMA :

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

Si no se devuelven filas, entonces la tabla no existe.


9

Después de leer todo lo anterior, prefiero la siguiente declaración:

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

Indica exactamente lo que quieres hacer y en realidad devuelve un 'booleano'.


2
Esta debería ser la respuesta aceptada. conciso y simple
Dika

esto no devuelve un booleano, devuelve un conjunto de resultados. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice


7

Aquí hay una tabla que no es un SELECT * FROM

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

Obtuve esto de una base de datos profesional, esto es lo que me dijeron:

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

Más fácil y eficiente.
e2-e4

3

Esta solución modificada de arriba no requiere un conocimiento explícito de la base de datos actual. Entonces es más flexible.

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

2

Solo para agregar una forma adicional de hacerlo, y dependiendo de lo que necesite, podría usar un controlador para er_no_such_table error: 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 tablas como 'nombre_tabla'

si esto devuelve filas> 0, la tabla existe


1

Puedes hacer algo como a continuación:

            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

Ampliando esta respuesta , se podría escribir una función que devuelva VERDADERO / FALSO en función de si existe o no una tabla:

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 devuelve 1 si existe 0 si no existe.

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

Puedes ponerlo en una función 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 ;

y llámalo

Select ExistTable('my_table');

devuelve 1 si existe 0 si no existe.


0

Yo uso esto 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;
    }

0

Hay varios problemas a tener en cuenta con las respuestas aquí:

1) INFORMATION_SCHEMA.TABLESlo hace no incluir tablas temporales.

2) Usar cualquier tipo de SHOWconsulta, es decirSHOW TABLES LIKE 'test_table' , forzará la devolución de un conjunto de resultados al cliente, que es un comportamiento no deseado para verificar si existe una tabla en el lado del servidor, desde un procedimiento almacenado que también devuelve un conjunto de resultados.

3) Como algunos usuarios mencionaron, debes tener cuidado con la forma en que usas SELECT 1 FROM test_table LIMIT 1 .

Si haces algo como:

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

No obtendrá el resultado esperado si la tabla tiene cero filas.

A continuación se muestra un procedimiento almacenado que funcionará para todas las tablas (incluso TEMPORAL).

Se puede usar 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;

El 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 ha sido mi procedimiento EXISTENTE 'ir a' que verifica las tablas temporales y normales. Este procedimiento funciona en MySQL versión 5.6 y superior. El parámetro @DEBUG es opcional. Se supone el esquema predeterminado, pero se puede concatenar a la tabla en la instrucción @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 ;

Aquí está la declaración de llamada de ejemplo con @debug en:

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

La variable @tblExists devuelve un valor booleano.


-1

Ninguna de las opciones, excepto SELECT, no permite el nombre de la base de datos como se usa en SELECT, así que escribí esto:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.