Проверьте, существует ли таблица, не используя «выбрать из»


176

Есть ли способ проверить, существует ли таблица, не выбирая и не проверяя значения из нее?

То есть я знаю, что могу пойти SELECT testcol FROM testtableи проверить количество возвращаемых полей, но, похоже, должен быть более прямой / элегантный способ сделать это.


Посетите stackoverflow.com/a/167680/12495091 для ответа !!!!!!!!!
Саурабх Чопра

@SaurabhChopra Это для SQL Server, это вопрос о MySql.
Алехандро

Ответы:


323

Если вы хотите быть правы, используйте INFORMATION_SCHEMA .

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

Кроме того, вы можете использовать SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Если в наборе результатов есть строка, таблица существует.


3
Да, это работает хорошо и элегантно, но все еще использует SELECT...FROMсинтаксис ... Я искал что-то вродеEXISTS testtable
Бен

9
То, как мы с Марком заявили об этом, - правильный путь. Не существует оператора типа «существует» MySql. «Exists» в MySql - это предложение, которое требует таких операций, как SELECT, UPDATE или DELETE.
doogle

@Steve Третий вариант не является переносимым.
ta.speot.is

1
@SergioTulentsev Независимо от тега я предпочитаю портативный способ проприетарному.
ta.speot.is

1
@Filype это на самом деле не проблема, так как он только проверяет, успешно ли выполнен запрос. В случае, когда в таблице нет строк, запрос все равно будет выполнен успешно, только с пустым набором результатов.
Билл Дами

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

если вы получите ненулевой счет, таблица существует.


2
Я действительно не понимаю, что здесь произошло. Я проверил ответы, потому что я делаю это сейчас, и это правда, что ответ Серхио Туленцева был раньше (1 минута) и предложил 3 решения, но это самое эффективное. Почему я должен выбрать что-то еще или что-то еще, что я хочу? Мне нужна "логическая" 1/0 в этом случае. Таблица существует или нет. Я не хочу все ограничивать, я не хочу ничего любить, я не хочу никаких ошибок. Это должен быть принятый ответ.
vaso123

1
Обратите внимание, что на TEMPORARY TABLEэто не работает.
Томас Лобкер

27

Сравнение производительности:

  • MySQL 5.0.77, на базе данных, которая имеет около 11 000 таблиц.
  • Выбор неиспользуемой таблицы, чтобы она не кэшировалась.
  • В среднем более 10 попыток каждый. (Примечание: сделано с разными таблицами, чтобы избежать кеширования).

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

Обратите внимание, что если вы выполняете это много - например, по многим HTML-запросам за короткий период - второй будет намного быстрее, поскольку он будет кэшироваться в среднем 200 мс или быстрее.


16

Вы можете запросить tablesсистемное представление INFORMATION_SCHEMA :

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

Если строки не возвращены, то таблица не существует.


9

Прочитав все вышеизложенное, я предпочитаю следующее утверждение:

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

Он точно указывает, что вы хотите сделать, и фактически возвращает «логическое значение».


2
это должен принятый ответ. краткий и простой
Дика

это не возвращает логическое значение, оно возвращает набор результатов. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
Camslice

7

Вместо того, чтобы полагаться на ошибки, вы можете запросить, INFORMATION_SCHEMA.TABLESсуществует ли таблица. Если есть запись, она существует. Если нет записи, ее не существует.


1
Ааа, теперь мы приближаемся! Я пойду попробую.
Бен

1
@Steve: это все еще SELECT FROM. :-)
Серхио Туленцев

7

Вот таблица, которая не является SELECT * FROM

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

Получил это из базы данных про, вот что мне сказали:

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

Самый простой и эффективный.
e2-e4

3

Это модифицированное решение сверху не требует явного знания текущей базы данных. Это тогда более гибко.

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

2

Просто чтобы добавить дополнительный способ сделать это, и в зависимости от того, что вам нужно, вы можете использовать обработчик для ошибки er_no_such_table : 1146 вот так:

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

показывать таблицы вроде 'table_name'

если это возвращает строки> 0, таблица существует


1

Вы можете сделать что-то вроде ниже:

            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

Развернув этот ответ , можно дополнительно написать функцию, которая возвращает TRUE / FALSE в зависимости от того, существует таблица или нет:

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

Этот компактный метод возвращает 1, если существует 0, если не существует.

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

Вы можете вставить в функцию 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 ;

и назовите это

Select ExistTable('my_table');

вернуть 1, если существует 0, если не существует.


0

Я использую это в 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

Здесь есть несколько вопросов, на которые следует обратить внимание:

1) INFORMATION_SCHEMA.TABLESвовсе не включают в себя временные таблицы.

2) Использование любого типа SHOWзапроса, т.е. SHOW TABLES LIKE 'test_table'вызовет возврат набора результатов клиенту, что является нежелательным поведением для проверки, существует ли таблица на стороне сервера, из хранимой процедуры, которая также возвращает набор результатов.

3) Как упоминали некоторые пользователи, вы должны быть осторожны с тем, как вы используете SELECT 1 FROM test_table LIMIT 1.

Если вы делаете что-то вроде:

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

Вы не получите ожидаемый результат, если таблица имеет ноль строк.

Ниже представлена ​​хранимая процедура, которая будет работать для всех таблиц (даже ВРЕМЕННЫХ).

Может использоваться как:

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;

Код:

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

Это была моя процедура 'EXISTS' для проверки как временных, так и обычных таблиц. Эта процедура работает в версии MySQL 5.6 и выше. Параметр @DEBUG является необязательным. Предполагается схема по умолчанию, но ее можно объединить с таблицей в операторе @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 ;

Вот пример оператора вызова с @debug:

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

Переменная @tblExists возвращает логическое значение.


-1

Ни один из параметров, кроме SELECT, не позволяет использовать имя базы данных, используемое в SELECT, поэтому я написал это:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.