mysql - 表内的 SQL 查询

标签 mysql security subquery badge

我正在构建一个与 StackExchange 徽章工作方式非常相似的徽章系统。为了查询个人徽章资格,最佳解决方案似乎是将 SQL 查询放在表中,以便它可以作为 cron 作业的一部分执行。

这是我正在考虑使用的查询样式:

SELECT u.user_id
FROM users u
WHERE (
    SELECT COUNT(*)
    FROM comments c
    WHERE c.user_id = u.user_id
) > 0
AND [$badge_id] NOT IN (
    SELECT b.badge_id
    FROM user_badges b
    WHERE b.user_id = u.user_id
)

表格最终看起来像这样:

badge_id |    name         |  description  | level |     hash     | query
---------+-----------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------
1        | Hello World     | First comment |   1   | 50a7c570f... | u.user_id FROM users u WHERE ( SELECT COUNT(*) FROM comments c WHERE c.user_id = u.user_id ) > 0
2        | Into the Breach | First thread  |   1   | 6b01e9348... | u.user_id FROM users u WHERE ( SELECT COUNT(*) FROM threads t WHERE t.user_id = u.user_id ) > 0

查询从数据库中获取,以SELECT 为前缀,然后附加AND [$badge_id] NOT IN (...) 子查询条件。然后它将 [$badge_id] 替换为当前徽章 ID。执行查询并返回应为其提供徽章的用户 ID 列表。

哈希字段用于存储查询的 HMAC-SHA1 哈希,使用 PHP 脚本中定义的 key 。这背后的想法是,即使发生 SQL 注入(inject)攻击,攻击者也无法访问脚本中的 key ,也无法伪造更危险的查询。

我有两个问题:

  1. 表中的 SQL 是一种非常糟糕的方法吗?如果是这样,为什么?我对其他选择持开放态度。
  2. 是否有更高效的查询来实现相同的查询?根据我的经验,子查询通常很慢。

我也很想知道 StackExchange 代码是如何做到这一点的。

如果您有任何问题,请随时提出。

干杯。

最佳答案

这听起来像是个坏主意。如果您更改架构怎么办?现在您必须使表中的每一行都无效。如果您愿意,我可能会使用触发器来记录“触发”徽章的操作。然后,cron 脚本可能会授予徽章。

在你的例子中,这是一个非常简单的查询来判断某人是否需要被授予评论徽章,所以我会直接从 CRON 处理它:

SELECT * FROM comments
LEFT JOIN users_badges ON users_badges.user_id = comments.user_id AND users_badges.description = 'First Comment'
WHERE users_badges.badge_id IS NULL
GROUP BY comments.user_id

理论上,您可以为每个返回的结果插入一个徽章记录。这超出了我的脑海,但你明白了。

对于更复杂的查询,我仍然可能会插入某种事件表来简化事情。这也有助于将您的实现分开一点——如果将来徽章的“描述”发生变化,您会怎么做?规范化将有助于这种事情。

关于mysql - 表内的 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8486625/

相关文章:

php - 想要使用 PDO 制作复选框过滤器

mysql - 使用联合选择时以两个不同的名称获取数据

mysql - 如何使用另一个表中的变量进行 UNION

java - Java和数据库中的多线程

asp.net - 缓解 Web 服务器上的 RsaCryptoServiceProvider 线程安全问题

mysql - 如何使用子查询将数据从 View 插入表中?

java - JAAS 的 SAML LoginModule 示例

java - 使用 bouncycaSTLe 解析证书

php - Laravel 5 用关系排序 Eloquent 模型

mysql - 被嵌套多表 MySQL 查询所困扰