MySQL可以检查文件是否存在吗?

MySQL可以检查文件是否存在吗?,mysql,file-exists,Mysql,File Exists,我有一个表,它保存了硬盘上真实文件的相对路径。例如: SELECT * FROM images --> id | path 1 | /files/1.jpg 2 | /files/2.jpg 我可以创建一个查询来选择指向不存在文件的所有记录吗?我需要通过MySql服务器准确地检查它,而不需要在PHP客户端中使用迭代。MySql只处理数据库,因此您无法启动SQL语句来检查硬盘上是否存在该文件。您需要迭代这些行并使用PHP进行检查。我将使用如下查询: SELECT id, path, I

我有一个表,它保存了硬盘上真实文件的相对路径。例如:

SELECT * FROM images -->
id | path
1  | /files/1.jpg
2  | /files/2.jpg

我可以创建一个查询来选择指向不存在文件的所有记录吗?我需要通过MySql服务器准确地检查它,而不需要在PHP客户端中使用迭代。

MySql只处理数据库,因此您无法启动SQL语句来检查硬盘上是否存在该文件。您需要迭代这些行并使用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

使用股票MySQL是不可能的。但是,您可以编写(用户定义函数),可能是用C编写,使用语句加载它,并从MySQL使用它,就像使用任何内置函数一样。

MySQL
load\u FILE
命令对它可以打开的文件有非常严格的要求。从MySQL文档:

[
LOAD\u FILE
]读取文件并以字符串形式返回文件内容。要使用此功能,文件必须位于服务器主机上,必须指定文件的完整路径名,并且必须具有文件权限。该文件必须可供所有人读取,并且其大小必须小于允许的最大数据包字节数。如果secure_file_priv系统变量设置为非空目录名,则要加载的文件必须位于该目录中

因此,如果
mysql
用户无法访问该文件,或者不满足任何其他要求,
LOAD\u file
将返回
Null


您可以使用
awk
获取与丢失文件相对应的ID列表:

mysql db_name --batch -s -e "SELECT id, path FROM images" \ | awk '{if(system("[ -e " $2 " ]") == 1) {print $1}}' \ >> missing_ids.txt
这还有一个优点,就是比加载文件快得多。这是一个非常糟糕的设计。我不相信MySQL可以通过这种方式访问文件系统。你需要使用外部语言来实现这一点。博格丹·布里姆,为什么不好?最好是将图像数据放在二进制字段中,或者什么?看看是否可以为您尝试实现的目标提供建议。我想可能是,如果mysql具有加载数据填充等功能,换句话说,它可以访问用户文件,然后它可以检查文件是否存在。或者你可以将你的文件作为二进制大对象BLOB存储在数据库中,并检查它们是否存在于数据库中,mysql自定义创建的函数仅使用SQL。@MatteoTassinari请阅读链接的资源。您可以创建用SQL编写的“存储函数”,也可以创建“用户定义函数”,这些函数被编译到共享库中并在运行时加载。很抱歉,当时我似乎错了,谢谢您指出:)我自己无法实现这一点。返回的所有文件实际上都存在。什么可能意味着MySQL无法读取此本地位置?可能是运行MySQL守护程序的用户无法访问包含这些文件的文件夹。
HAVING not_exists=1
部分是错误的,因为您没有按not_exists进行分组。如果只想选择文件所在的行,则应执行如下操作:
select id,path FROM images,其中LOAD_file(path)为NULL
;是的,它不是标准的SQL,但MySQL允许它。但我喜欢你的建议,我会修改我的答案:)这似乎是浪费。LOAD_FILE函数将读取每个确实存在的文件的内容。这使得这个查询毫无意义地使用了大量的I/O。仅仅因为某人能做某事并不意味着这是一个好主意。这个任务最好是以脚本的形式编写!如果文件名包含圆括号“()”,则此命令会引发错误。有没有办法让它可以处理任何类型的文件名?@CarstenSchmitz我添加了一个使用bash while循环的示例。你可以试着用它来代替。 mysql db_name --batch -s -e "SELECT id, path FROM images" \ | while read id path ; if [[ -e "$path" ]] ; then echo $id ; done >> missing_ids.txt