检查MySQL表是否存在,不使用“;select from”;语法呢?

是否有一种方法来检查表是否存在没有选择和检查它的值?

也就是说,我知道我可以SELECT testcol FROM testtable并检查返回的字段的计数,但似乎必须有一个更直接/优雅的方式来做到这一点。

357336 次浏览

如果你想要正确,使用INFORMATION_SCHEMA

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

或者,你也可以使用SHOW TABLES

SHOW TABLES LIKE 'yourtable';

如果结果集中有行,则表存在。

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

如果得到非零计数,则表存在。

您可以查询INFORMATION_SCHEMA tables系统视图:

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

如果没有返回行,则表不存在。

而不是依赖于错误,你可以查询INFORMATION_SCHEMA.TABLES来查看表是否存在。如果有记录,那就是存在的。如果没有记录,它就不存在。

除了SELECT选项,其他选项都不允许使用SELECT中的数据库名称,所以我这样写:

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

下面是一个不是SELECT * FROM的表

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

这是从一个数据库专家那里得到的,这是我被告知的:

select 1 from `tablename`; //avoids a function call
select * from INFORMATION_SCHEMA.tables where schema = 'db' and table = 'table' // slow. Field names not accurate
SHOW TABLES FROM `db` LIKE 'tablename'; //zero rows = does not exist

只是为了增加一种额外的方法来实现它,并且在你需要它的地方使用根据,你可以使用处理程序来处理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 ;

你可以这样做:

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

我在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;
}

性能比较:

  • MySQL 5.0.77,在一个大约有11000个表的数据库上。
  • 选择一个非最近使用的表,这样它就不会被缓存。
  • 平均每次超过10次。(注意:做不同的表,以避免缓存)。

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

注意,如果你经常运行这个,比如在短时间内处理很多HTML请求,第2个会更快,因为它平均缓存200毫秒或更快。

显示像'table_name'这样的表

如果返回行> 0,则表存在

上述修改后的解决方案不需要明确了解当前数据库。这样就更灵活了。

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

扩展回答,可以进一步编写一个函数,根据表是否存在返回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');

在阅读了以上所有内容后,我更喜欢以下说法:

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

它确切地指出你想做什么,它实际上返回一个'布尔'

这里的答案有几个问题需要注意:

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

如果表中没有行,则不会得到预期的结果。

下面是一个适用于所有表(甚至是TEMPORARY表)的存储过程。

它可以这样使用:

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 ;

这是我的“去”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 on的示例调用语句:

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

变量@tblExists返回一个布尔值。

如果存在则返回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。

如果在2019年之后阅读这篇文章,请注意MySQL 5.7添加了table_exists过程,它将确定一个表是否存在,包括临时表。

< p >用法:

. set @exist为'BASE TABLE', 'VIEW', 'TEMPORARY'中的一个
CALL sys.table_exists('db1', 't3', @exists);

参考:

https://dev.mysql.com/doc/refman/5.7/en/sys-table-exists.html

在创建TABLE之前,最好先检查SQL Server数据库中是否存在该表。

USE [DB_NAME]
GO
IF OBJECT_ID('table_name', 'U') IS NOT NULL
BEGIN
PRINT 'Table exists.'
END
ELSE
BEGIN
PRINT 'Table does not exist.'
END
< p >或者 使用sys。

. SQL Server中是否存在表
USE [DB_NAME]
GO
IF EXISTS(SELECT 1 FROM sys.Objects
WHERE Object_id = OBJECT_ID(N'table_name')
AND Type = N'U')
BEGIN
PRINT 'Table exists.'
END
ELSE
BEGIN
PRINT 'Table does not exist.'
END