美文网首页
判断从表的外键是否包含所有主表的主键

判断从表的外键是否包含所有主表的主键

作者: 回调的幸福时光 | 来源:发表于2018-08-13 21:07 被阅读17次

    我们知道数据库中有以下几个概念:

    • 主键:一般情况下,满足第一范式的表都有一个主键Primary key,用于唯一标示数据库中的一个字段
    • 外键: 外键是相对于数据库设计中的参考完整性而言,它与主键之间是彼此依赖的关系。
    • 主表: 在数据库中建立的表格即Table,其中存在主键(primary key)用于与其它表相关联,并且作为在主表中的唯一性标识
    • 从表: 以主表的主键(primary key)值为外键 (Foreign Key)的表,可以通过外键与主表进行关联查询。从表与主表通过外键进行关联查询

    有如下两个表,主表是fansArr,是粉丝的信息记录。主键:fans_id,格式为 xxx-xxx-xx 表示一个32位的字符,避免重复。

    const fansArr = [
        {
            fans_id: 'xxx-xxx-xx1',
            name: 'xx'
        },
        {
            fans_id: 'xxx-xxx-xx2',
            name: 'xy'
        }
    ];
    

    从表是imgArr, 是所有粉丝图片的记录。外键是 fansId,

    const imgArr = [
        {
            fansId: 'xxx-xxx-xx1',
            imgUrl: 'xxxx.jpg'
        },
        {
            fansId: 'xxx-xxx-xx1',
            imgUrl: 'xxxx.jpg'
        },
        {
            fansId: 'xxx-xxx-xx2',
            imgUrl: 'xxxx.jpg'
        },
        {
            fansId: 'xxx-xxx-xx1',
            imgUrl: 'xxxx.jpg'
        }
    ];
    

    不难发现,粉丝和粉丝个人图片是 一对多 的关系。

    问题

    现在有个需求,每个粉丝至少一张图片,怎么校验?

    解法一: 外键去重
    弊端:性能低,因为一对多的关系,当外表记录的信息太多时,遍历次数太多。

     /**
      * 遍历 imgArr 数组,得到所有 fansId 
      */
    function emptyFn1() {
        let arr = [];
        imgArr.forEach( img => {
            if(!arr.includes(img.fansId)) {
                arr.push(img.fansId)
            }
        })
        return arr.length !== fansArr.length
    }
    

    哈哈哈,方法一并不总是有效的!!!仔细看看问题出在哪里?
    理想情况下外表是根据主表的主键作为外键来记录信息的,但是如果主表的主键改了,而外表的外键没有更改,方法一只是保证了主键和外键的数量一致,但内容不一定一样。不信把 fansArr[0].fans_id 改成 xxx-xxx-xx3 试试

    解法二: 遍历主表,获取所有在从表中出现的fans_id

     function emptyFn2() {
        let arr = [];
        let str = JSON.stringify(imgArr);
        fansArr.forEach(fans => {
            if(str.includes(fans.fans_id)) {
                arr.push(fans.fans_id)
            }
        })
        return arr.length !== fansArr.length
    }
    

    对解法二的优化:forEach 会遍历所有,实际可能并不需要遍历全部

    function emptyFn3() {
        let str = JSON.stringify(imgArr);
           if(fansArr.length > 0) {
            return !fansArr.every(fans => {
                return str.includes(fans.fans_id)
            })
        }
        throw new Error('主表是空的');
    }
    

    方法 二、三的弊端
    fans_id 如果不是唯一的字符串,则存在不确定性
    例如 fans_id 是普通的 1, 2, 3, 则字符串中可能存在干扰项

    相关文章

      网友评论

          本文标题:判断从表的外键是否包含所有主表的主键

          本文链接:https://www.haomeiwen.com/subject/yzfpbftx.html