Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mySQL:获取每行的哈希值?_Mysql_Hash - Fatal编程技术网

mySQL:获取每行的哈希值?

mySQL:获取每行的哈希值?,mysql,hash,Mysql,Hash,目前,我正在手动创建一个字符串,将表中每行中的所有值连接在一起。我将对每一行的这个字符串进行散列,以获得该行当前值(/status)的散列值,稍后我将使用该散列值来确定该行是否已更改 是否有一种内置方式可以代替手动执行此操作,从而为每行获取唯一的哈希值?您可以执行以下操作 SELECT MD5(concat(field1, field2, field3, ...)) AS rowhash 但是你不能不列出你想要的字段,因为concat(*)不是一个选项(语法错误)。最好使用concat\u w

目前,我正在手动创建一个字符串,将表中每行中的所有值连接在一起。我将对每一行的这个字符串进行散列,以获得该行当前值(/status)的散列值,稍后我将使用该散列值来确定该行是否已更改


是否有一种内置方式可以代替手动执行此操作,从而为每行获取唯一的哈希值?

您可以执行以下操作

SELECT MD5(concat(field1, field2, field3, ...)) AS rowhash

但是你不能不列出你想要的字段,因为
concat(*)
不是一个选项(语法错误)。

最好使用concat\u ws()。e、 g.两个相邻列:12,3=>1,23

抱歉,这仍然有一些问题。考虑空值、空字符串、字符串可以包含“,”等


需要一个程序来生成hash语句,它应该将null替换为特定的值(对于可为null的列),并且还使用很少使用的char/byte作为分隔符。

我制作了一个小脚本,可以完全满足您的需要,也可以满足其他人的需要。。。这就是PHP,它是。。。 首先,您必须列出表中的列,然后根据列的类型为每列创建一个“case-when”语句,并将其放入concat_-ws语句中,然后使用sha1对其进行散列…我在非常大的表(600000多条记录)上使用了此方法,在选择所有记录时,速度非常快。此外,我认为在concat_ws中浓缩所需数据并在php或您正在使用的任何东西中分解它会更快,但这只是一种预感

<?
$query= mysql_query("SHOW COLUMNS FROM $table", $linklive);
        while ($col = mysql_fetch_assoc($query)) {
            $columns[] = mysql_real_escape_string($col['Field']);
            if ($col['Key'] == 'PRI') {
                $key = mysql_real_escape_string($col['Field']);
            }
            $columnsinfo[$col['Field']] = $col;
        }
        $dates = array("date","datetime","time");
                    $int = array("int","decimal");
                    $implcols = array();
                    foreach($columns as $col){
                        if(in_array($columnsinfo[$col]['Type'], $dates)){
                            $implcols[] = "(CASE WHEN (UNIX_TIMESTAMP(`$col`)=0 || `$col` IS NULL) THEN '[$col EMPTY]' ELSE `$col` END)";
                        }else{
                            list($type, $rest) = explode("(",$columnsinfo[$col]['Type']);
                            if(in_array($columnsinfo[$col]['Type'], $dates)){
                                $implcols[] = "(CASE WHEN ( `$col`=0 || `$col` IS NULL ) THEN '[$col EMPTY]' ELSE `$col` END)";
                            }else{
                                $implcols[] = "(CASE WHEN ( `$col`='' || `$col` IS NULL ) THEN '[$col EMPTY]' ELSE `$col` END)";
                            }
                        }
                    }
                    $keyslive = array();
                    //echo "SELECT $key SHA1(CONCAT_WS('',".implode(",", $columns).")) as compare FROM $table"; exit;
                    $q = "SELECT $key as `key`, SHA1(CONCAT_WS('',".implode(", ",$implcols).")) as compare FROM $table";
    ?>

CONCAT存在问题,例如
CONCAT('ab','c')
vs
CONCAT('a','bc')
。两行不同,但结果相同。您可以使用
CONCAT_WS(“;”,“ab”,“c”)
获得
ab;c
但是在
CONCAT_-WS(“;”,“;”,“)
vs
CONCAT_-WS(“;”,“;”)
的情况下,仍然会得到相同的结果

另外
CONCAT(NULL,'c')
返回
NULL

我认为最好的方法是使用
引用

选择MD5(CONCAT(QUOTE(c1)、QUOTE(c2)、QUOTE(c3))作为t1中的行_散列

结果:
select(concat(quote('a')、quote('bc')、quote('NULL')、quote(NULL)、quote('\'')、quote(''))

是:
'a''bc''NULL'NULL'\''”

另外,不要使用GROUP_CONCAT()获取表的哈希,它有以下限制:

相反,
CHECKSUM TABLE
可能更好,但您不能跳过
CHECKSUM TABLE

晚到派对的列,但是…

您可以添加一个
updated
字段,该字段在行更改时更新。
然后你只需要跟踪时间戳,就像这样显示

updated: 2017-12-30 17:51:19 
这样不仅可以知道行是否更改,还可以知道上次更新的时间。
MySQL命令:

ALTER TABLE mytable ADD `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
默认精度为1秒(如果您只是不时检查行是否更改,那么这应该足够了)。但如果必要的话,你可以设置几分之一秒的精度,比如微秒

ALTER TABLE mytable ADD `updated` timestamp(6) NOT NULL
DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
然后,时间戳将显示为

updated: 2017-12-30 17:51:19.123456 

,这是针对8.0的,但我已经在5.7上成功地使用了它。

如果其中一个字段为空,这将不起作用。对于可为空的字段,您应该使用COALESCE(fieldX,“some_NULL_placeholder”)。@Mrskman文档说它会跳过separator参数后的任何空值(至少从MySQL 8.0开始就是这样)。()@aderchox CONCAT_WS()与CONCAT()不同;-)如果任何参数为NULL,CONCAT()将返回NULL。