php - 避免唯一约束与学说冲突的最佳方法是什么?

标签 php sql math doctrine-orm

SQL 表的顺序标识符的内在缺点是最终用户有可能轻松地遍历您的表。有时这是一个问题。

一个解决方案是创建一个非序列化的 id,每一行都不可猜测。

很明显,这个 id 必须是一个唯一的字段。我可以使用随机函数为每一行生成这些唯一 ID,但它有可能与先前设置的 ID 发生冲突。如果发生碰撞,最终用户会将其视为随机错误...

这里有一个解决这个问题的简单方法:

$keyValid = false;
while(!$keyValid) {
    // Create a new random key
    $newKey = generateKey();

    // Check if the key already exists in database
    $existingPotato = $em->getRepository('Potato')->findOneBy(array('key' => $newKey));
    if (empty($existingPotato)) {
        $keyValid = true;
    }
}

// Hooray, key is unique!

每次我想要一个新 ID 时,它都会强制我至少执行一个 SELECT 语句。

那么,是否有更好的、被广泛接受的解决方案来解决这个问题?

或者,是否有优化的 id 长度,通过使冲突概率可以忽略不计(对于 3,000,000 行的表)使这个问题无关紧要?

最佳答案

您可以添加 Custom id generation strategy去做吧。您可以通过创建一个扩展 AbstractIdGenerator 的类来实现它:

use Doctrine\ORM\Id\AbstractIdGenerator;

class NonSequencedIdGenerator extends AbstractIdGenerator
{
    public function generate(\Doctrine\ORM\EntityManager $em, $entity)
    {
        $class  = $em->getClassMetadata(get_class($entity));
        $entityName = $class->getName();

        do {
            // You can use uniqid(), http://php.net/manual/en/function.uniqid.php
            $id = generateKey();
        } while($em->find($entityName, $id));


        return $id;
    }
}

然后在您的实体类中使用注解添加它:

/**
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="CUSTOM")
 * @ORM\CustomIdGenerator(class="NonSequencedIdGenerator")
 */
private $id;

但是如果您的 generateKey 没有返回唯一标识符,您应该检查它是否已经存在。为避免这种情况,您也可以为实体中的主键使用 UUID 生成器。

/**
 * @ORM\Id
 * @ORM\Column(type="guid", unique=true)
 * @ORM\GeneratedValue(strategy="UUID")
 */
private $id;

如果您不喜欢这样,您可以使用 UUID_SHORT 创建一个新的自定义 ID 生成,并使用类似 this 的函数使其更短。

use Doctrine\ORM\Id\AbstractIdGenerator;

class UuidShortGenerator extends AbstractIdGenerator
{
    public function generate(EntityManager $em, $entity)
    {
        $conn = $em->getConnection();
        return $conn->query('SELECT UUID_SHORT()')->fetchColumn(0);
    }
}

这里的问题是我不认为它提供了完整的可移植性。

关于php - 避免唯一约束与学说冲突的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33053079/

相关文章:

PHP/MySQL - 内连接排名

math - 如何计算沿圆柱体切片的两点之间的 SVG 路径弧

php - yii2 在 ActiveDataProvider 中合并来自多个查询的数据

php - str_replace 数组

mysql - MySQL 中 CASE 语句中的 REGEXP

sql - 在一个脚本中创建 SQL Server 表和存储过程?

python - python 中的“力量”

python - 求两个矩形的交集和并集

php - 如何使用 php 脚本将组合框和单选按钮值存储到 mysql 数据库?

mysql - 是否有数据库级别的软删除机制