我有一个表,其中包含 HDD 上真实文件的相对路径。例如:
SELECT * FROM images -->
id | path
1 | /files/1.jpg
2 | /files/2.jpg
我可以创建一个查询来选择所有指向不存在文件的记录吗?我需要通过 MySql 服务器准确地检查它,而不是在 PHP 客户端中使用迭代。
我有一个表,其中包含 HDD 上真实文件的相对路径。例如:
SELECT * FROM images -->
id | path
1 | /files/1.jpg
2 | /files/2.jpg
我可以创建一个查询来选择所有指向不存在文件的记录吗?我需要通过 MySql 服务器准确地检查它,而不是在 PHP 客户端中使用迭代。
我会使用这样的查询:
SELECT id, path, ISNULL(LOAD_FILE(path)) as not_exists
FROM images
HAVING not_exists = 1
该函数LOAD_FILE
尝试将文件作为字符串加载,并NULL
在失败时返回。
请注意,这种情况下的失败可能是由于 mysql 根本无法读取该特定位置,即使该文件确实存在。
编辑:
正如@ostrokach 在评论中指出的那样,这不是标准 SQL,即使 MySQL 允许它遵循它可能的标准:
SELECT *
FROM images
WHERE LOAD_FILE(PATH) IS NULL
MySQLLOAD_FILE
命令对可以打开的文件有非常严格的要求。来自 MySQL 文档:
[
LOAD_FILE
] 读取文件并将文件内容作为字符串返回。要使用此功能,文件必须位于服务器主机上,您必须指定文件的完整路径名,并且您必须具有 FILE 权限。该文件必须可供所有人读取,并且其大小小于 max_allowed_packet 字节。如果将secure_file_priv 系统变量设置为非空目录名,则要加载的文件必须位于该目录中。
因此,如果用户无法访问该文件mysql
或不满足任何其他要求,LOAD_FILE
将返回Null
.
您可以使用以下命令获取与丢失文件相对应的 ID 列表awk
:
mysql db_name --batch -s -e "SELECT id, path FROM images" \ | awk '{if(system("[ -e " $2 " ]") == 1) {print $1}}' \ >> 缺少_ids.txt
或简单地使用bash
:
mysql db_name --batch -s -e "SELECT id, path FROM images" \ | 同时读取 id 路径;如果 [[ -e "$path" ]] ; 然后回显 $id ;完毕 >> 缺少_ids.txt
这还具有比LOAD_FILE
.
MYSQL 仅处理数据库,因此如果文件存在,您无法触发 SQL 语句来检查 HDD。您需要遍历行并使用 PHP 进行检查。
使用股票 MySQL 是不可能的。但是,您可以编写UDF (用户定义函数),可能在 C 中,使用CREATE FUNCTION语句加载它并从 MySQL 中使用它,就像使用任何内置函数一样。