从 mysql 更新到 mysqli 后数据库查询中断

Posted

技术标签:

【中文标题】从 mysql 更新到 mysqli 后数据库查询中断【英文标题】:Database query broken since updating from mysql to mysqli 【发布时间】:2015-05-26 22:53:04 【问题描述】:

我继承了一个网站,该网站有一系列最初使用 mysql_query 编码的数据库查询。 由于 zen cart 的更新,从 mysql 移动到 mysqli 这些查询必须更新。由于将查询更改为 mysqli,因此该功能已损坏。

原来的查询是:

function insert_FENQUIRY() 
            $sql = sprintf('INSERT INTO FENQUIRY
                (ENREGION, ENNAME, ENCOMP, ENADD1, ENADD2, ENADD3, ENCNTY, ENPCODE, ENCNTRY, ENTEL, ENDATE, ENDATELCON, ENCAT, ENCONSRS, ENADVER, ENTYPE, EN_CUSTOMER_ID)
                SELECT
                    (SELECT region FROM postcode2region WHERE ab.entry_postcode REGEXP CONCAT("^", postcode_prefix, "[:digit:]*") ORDER BY postcode_prefix DESC LIMIT 1) AS ENREGION,
                    c.ENCONNAME AS ENNAME,
                    IF(ab.entry_company <> "", ab.entry_company, CONCAT(c.ENCONNAME, " - online")) AS ENCOMP,
                    ab.entry_street_address AS ENADD1,
                    ab.entry_suburb AS ENADD2,
                    ab.entry_city AS ENADD3,
                    ab.entry_state AS ENCNTY,
                    ab.entry_postcode AS ENPCODE,
                    cc.countries_name AS ENCNTRY,
                    c.ENCONTEL AS ENTEL,
                    CURDATE() AS ENDATE,
                    CURDATE() AS ENDATELCON,
                    "X" AS ENCAT,
                    1 AS ENCONSRS,
                    "WWW" AS ENADVER,
                    "70" AS ENTYPE,
                    c.ENCON_ID AS EN_CUSTOMER_ID
                FROM FENQCON c
                LEFT JOIN address_book ab ON ab.address_book_id = c.ENCON_ZEN_DEFAULT_ADDRESS_ID
                LEFT JOIN countries cc ON cc.countries_id = ab.entry_country_id
                WHERE c.ENCON_ID = %d
                LIMIT 1',
                $_SESSION['customer_id']);
            mysql_query($sql) or error_log("KG insert_FENQUIRY() : ". mysql_error());
            return mysql_insert_id();
        

        function insert_FENQCON() 
            global $firstname, $lastname, $password, $gender, $newsletter, $email_format, $email_address,
                $telephone, $fax, $company, $postcode;
            $q = mysql_query(sprintf('
                INSERT INTO FENQCON
                SET
                ENCONFNAME = "%s",
                ENCONLNAME = "%s",
                ENCON_ZEN_PASSWORD = "%s",
                ENCON_ZEN_GENDER = "%s",
                ENCON_ZEN_NEWSLETTER = "%s",
                ENCON_ZEN_EMAIL_FORMAT = "%s",
                ENCON_ZEN_AUTHORIZATION = "%s",
                ENCONEMAIL = "%s",
                ENCONTEL = "%s",
                ENCONFAX = "%s",
                ENCONDATE = CURDATE(),
                ENCONNAME = "%s",
                ENCON_OPTIN = 1,
                ENCON_ZEN_ISLOGIN = 1
                ',
                mysql_escape_string($firstname),
                mysql_escape_string($lastname),
                zen_encrypt_password($password),
                mysql_escape_string($gender),
                (int) $newsletter,
                mysql_escape_string($email_format),
                (int) CUSTOMERS_APPROVAL_AUTHORIZATION,
                mysql_escape_string($email_address),
                mysql_escape_string($telephone),
                mysql_escape_string($fax),
                mysql_escape_string("$firstname $lastname")
            )) or die(mysql_error());
            return mysql_insert_id();
        

        function update_FENQCON_with_login() 
            global $firstname, $lastname, $password, $gender, $newsletter, $email_format;

            $q = mysql_query(sprintf('
                UPDATE FENQCON
                    SET
                        ENCONFNAME = "%s",
                        ENCONLNAME = "%s",
                        ENCON_ZEN_PASSWORD = "%s",
                        ENCON_ZEN_GENDER = "%s",
                        ENCON_ZEN_NEWSLETTER = "%s",
                        ENCON_ZEN_EMAIL_FORMAT = "%s",
                        ENCON_ZEN_AUTHORIZATION = "%s",
                        ENCON_ZEN_ISLOGIN = 1,
                        ENCONCUSTOMER_ID = %d
                    WHERE ENCON_ID = %d',
                mysql_escape_string($firstname),
                mysql_escape_string($lastname),
                zen_encrypt_password($password),
                mysql_escape_string($gender),
                (int) $newsletter,
                mysql_escape_string($email_format),
                (int) CUSTOMERS_APPROVAL_AUTHORIZATION,
                $_SESSION['customer_id'],
                $_SESSION['customer_id']    // WHERE
            )) or die(mysql_error());
        

        // FENQUIRY FLAG
        $flag_insert_into_FENQUIRY = false;

        // Check if email exists in FENQCON
        $sql = sprintf('
            SELECT
                c.ENCON_ID,
                c.ENCONCODE,
                c.ENCONFNAME,
                c.ENCONLNAME,
                c.ENCONCSUNIQUE,
                q.ENPCODE,
                q.ENCOMP,
                (SOUNDEX(c.ENCONFNAME) = SOUNDEX("%1$s")) * 1
                    +(SOUNDEX(c.ENCONLNAME) = SOUNDEX("%2$s")) * 1
                    +ROUND(levenshtein_ratio(REPLACE(q.ENPCODE, " ", ""), REPLACE("%4$s", " ", "")) / 100 * 2)
                    +ROUND(levenshtein_ratio(q.ENCOMP, "%5$s") / 100 * 2)
                    AS Score
            FROM FENQCON c
            LEFT JOIN FENQUIRY q ON q.ENCSUNIQUE = c.ENCONCSUNIQUE
            WHERE c.ENCONEMAIL = "%3$s"
            ORDER BY Score DESC, c.ENCON_ID ASC
            LIMIT 1',
            mysql_escape_string($firstname),        // %1
            mysql_escape_string($lastname),         // %2
            mysql_escape_string($email_address),    // %3
            mysql_escape_string($postcode),         // %4
            mysql_escape_string($company)           // %5
            );
        $q = mysql_query($sql) or die(mysql_error());

        if (mysql_num_rows($q) == 1)       // We have a matching existing FENQCON row
            $FENQCON = mysql_fetch_object($q);
            mysql_free_result($q);
            error_log("KG FENQCON exists: ". print_r($FENQCON, true));

            $_SESSION['customer_id'] = $FENQCON->ENCON_ID ;

            $FENQUIRY = null;
            if ($FENQCON->ENCONCSUNIQUE > 0)       // Fetch a linked FENQUIRY row if it exists and is linked!
                $q = mysql_query(sprintf('SELECT * FROM FENQUIRY WHERE ENCSUNIQUE = %d', $FENQCON->ENCONCSUNIQUE));
                $FENQUIRY = mysql_fetch_object($q);
                mysql_free_result($q);
            

            update_FENQCON_with_login();

            if ($FENQUIRY) 
                // Nothing to do                    
             else                     
                $flag_insert_into_FENQUIRY = true;                  
            
         else     // We need to create a new FENQCON and FENQUIRY rows
            error_log("KG No matching FENQCON found.");             
            $_SESSION['customer_id'] = insert_FENQCON();
            error_log("KG New FENQCON added with ENCON_ID: ". $_SESSION['customer_id']);

            $flag_insert_into_FENQUIRY = true;
        

此时一切正常。 如下所示更新了查询以使用 mysqli,它现在仅部分起作用。

            function insert_FENQUIRY() 
            $connect = mysqli_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE);
            $sql = sprintf('INSERT INTO FENQUIRY
                (ENREGION, ENNAME, ENCOMP, ENADD1, ENADD2, ENADD3, ENCNTY, ENPCODE, ENCNTRY, ENTEL, ENDATE, ENDATELCON, ENCAT, ENCONSRS, ENADVER, ENTYPE, EN_CUSTOMER_ID)
                SELECT
                    (SELECT region FROM postcode2region WHERE ab.entry_postcode REGEXP CONCAT("^", postcode_prefix, "[:digit:]*") ORDER BY postcode_prefix DESC LIMIT 1) AS ENREGION,
                    c.ENCONNAME AS ENNAME,
                    IF(ab.entry_company <> "", ab.entry_company, CONCAT(c.ENCONNAME, " - online")) AS ENCOMP,
                    ab.entry_street_address AS ENADD1,
                    ab.entry_suburb AS ENADD2,
                    ab.entry_city AS ENADD3,
                    ab.entry_state AS ENCNTY,
                    ab.entry_postcode AS ENPCODE,
                    cc.countries_name AS ENCNTRY,
                    c.ENCONTEL AS ENTEL,
                    CURDATE() AS ENDATE,
                    CURDATE() AS ENDATELCON,
                    "X" AS ENCAT,
                    1 AS ENCONSRS,
                    "WWW" AS ENADVER,
                    "70" AS ENTYPE,
                    c.ENCON_ID AS EN_CUSTOMER_ID
                FROM FENQCON c
                LEFT JOIN address_book ab ON ab.address_book_id = c.ENCON_ZEN_DEFAULT_ADDRESS_ID
                LEFT JOIN countries cc ON cc.countries_id = ab.entry_country_id
                WHERE c.ENCON_ID = %d
                LIMIT 1',
                $_SESSION['customer_id']);
            mysqli_query($connect,$sql) or error_log("KG insert_FENQUIRY() : ". mysql_error());
            return mysqli_insert_id($connect);
        

        function insert_FENQCON() 
            global $firstname, $lastname, $password, $gender, $newsletter, $email_format, $email_address,
                $telephone, $fax, $company, $postcode;
            $connect = mysqli_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE);
            $q = mysqli_query($connect,sprintf('
                INSERT INTO FENQCON
                SET
                ENCONFNAME = "%s",
                ENCONLNAME = "%s",
                ENCON_ZEN_PASSWORD = "%s",
                ENCON_ZEN_GENDER = "%s",
                ENCON_ZEN_NEWSLETTER = "%s",
                ENCON_ZEN_EMAIL_FORMAT = "%s",
                ENCON_ZEN_AUTHORIZATION = "%s",
                ENCONEMAIL = "%s",
                ENCONTEL = "%s",
                ENCONFAX = "%s",
                ENCONDATE = CURDATE(),
                ENCONNAME = "%s",
                ENCON_OPTIN = 1,
                ENCON_ZEN_ISLOGIN = 1
                ',
                mysqli_escape_string($connect,$firstname),
                mysqli_escape_string($connect,$lastname),
                zen_encrypt_password($password),
                mysqli_escape_string($connect,$gender),
                (int) $newsletter,
                mysqli_escape_string($connect,$email_format),
                (int) CUSTOMERS_APPROVAL_AUTHORIZATION,
                mysqli_escape_string($connect,$email_address),
                mysqli_escape_string($connect,$telephone),
                mysqli_escape_string($connect,$fax),
                mysqli_escape_string($connect,"$firstname $lastname")
            )) or die(mysqli_error());
            return mysqli_insert_id($connect);
        

        function update_FENQCON_with_login() 
            global $firstname, $lastname, $password, $gender, $newsletter, $email_format;
            $connect = mysqli_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE);
            $q = mysqli_query($connect,sprintf('
                UPDATE FENQCON
                    SET
                        ENCONFNAME = "%s",
                        ENCONLNAME = "%s",
                        ENCON_ZEN_PASSWORD = "%s",
                        ENCON_ZEN_GENDER = "%s",
                        ENCON_ZEN_NEWSLETTER = "%s",
                        ENCON_ZEN_EMAIL_FORMAT = "%s",
                        ENCON_ZEN_AUTHORIZATION = "%s",
                        ENCON_ZEN_ISLOGIN = 1,
                        ENCONCUSTOMER_ID = %d
                    WHERE ENCON_ID = %d',
                mysqli_escape_string($connect,$firstname),
                mysqli_escape_string($connect,$lastname),
                zen_encrypt_password($password),
                mysqli_escape_string($connect,$gender),
                (int) $newsletter,
                mysqli_escape_string($connect,$email_format),
                (int) CUSTOMERS_APPROVAL_AUTHORIZATION,
                $_SESSION['customer_id'],
                $_SESSION['customer_id']    // WHERE
            )) or die(mysqli_error());
        

        // FENQUIRY FLAG
        $flag_insert_into_FENQUIRY = false;

        // Check if email exists in FENQCON
        $connect = mysqli_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE);
        $sql = sprintf('
            SELECT
                c.ENCON_ID,
                c.ENCONCODE,
                c.ENCONFNAME,
                c.ENCONLNAME,
                c.ENCONCSUNIQUE,
                q.ENPCODE,
                q.ENCOMP,
                (SOUNDEX(c.ENCONFNAME) = SOUNDEX("%1$s")) * 1
                    +(SOUNDEX(c.ENCONLNAME) = SOUNDEX("%2$s")) * 1
                    +ROUND(levenshtein_ratio(REPLACE(q.ENPCODE, " ", ""), REPLACE("%4$s", " ", "")) / 100 * 2)
                    +ROUND(levenshtein_ratio(q.ENCOMP, "%5$s") / 100 * 2)
                    AS Score
            FROM FENQCON c
            LEFT JOIN FENQUIRY q ON q.ENCSUNIQUE = c.ENCONCSUNIQUE
            WHERE c.ENCONEMAIL = "%3$s"
            ORDER BY Score DESC, c.ENCON_ID ASC
            LIMIT 1',
            mysqli_escape_string($connect,$firstname),      // %1
            mysqli_escape_string($connect,$lastname),           // %2
            mysqli_escape_string($connect,$email_address),  // %3
            mysqli_escape_string($connect,$postcode),           // %4
            mysqli_escape_string($connect,$company)         // %5
            );
        $q = mysqli_query($connect,$sql) or die(mysqli_error());

        if (mysqli_num_rows($q) == 1)      // We have a matching existing FENQCON row
            $FENQCON = mysqli_fetch_object($q);
            mysqli_free_result($q);
            error_log("KG FENQCON exists: ". print_r($FENQCON, true));

            $_SESSION['customer_id'] = $FENQCON->ENCON_ID ;

            $FENQUIRY = null;
            if ($FENQCON->ENCONCSUNIQUE > 0)       // Fetch a linked FENQUIRY row if it exists and is linked!
                $q = mysqli_query($connect,sprintf('SELECT * FROM FENQUIRY WHERE ENCSUNIQUE = %d', $FENQCON->ENCONCSUNIQUE));
                $FENQUIRY = mysqli_fetch_object($q);
                mysqli_free_result($q);
            

            update_FENQCON_with_login();

            if ($FENQUIRY) 
                // Nothing to do                    
             else                     
                $flag_insert_into_FENQUIRY = true;                  
            
         else     // We need to create a new FENQCON and FENQUIRY rows
            error_log("KG No matching FENQCON found.");

            $_SESSION['customer_id'] = insert_FENQCON();
            error_log("KG New FENQCON added with ENCON_ID: ". $_SESSION['customer_id']);

            $flag_insert_into_FENQUIRY = true;
        

错误日志显示

php Warning:  mysqli_error() expects exactly 1 parameter, 0 given

这个错误发生在

$q = mysqli_query($connect,$sql) or die(mysqli_error());

以下代码段

$connect = mysqli_connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE);
        $sql = sprintf('
            SELECT
                c.ENCON_ID,
                c.ENCONCODE,
                c.ENCONFNAME,
                c.ENCONLNAME,
                c.ENCONCSUNIQUE,
                q.ENPCODE,
                q.ENCOMP,
                (SOUNDEX(c.ENCONFNAME) = SOUNDEX("%1$s")) * 1
                    +(SOUNDEX(c.ENCONLNAME) = SOUNDEX("%2$s")) * 1
                    +ROUND(levenshtein_ratio(REPLACE(q.ENPCODE, " ", ""), REPLACE("%4$s", " ", "")) / 100 * 2)
                    +ROUND(levenshtein_ratio(q.ENCOMP, "%5$s") / 100 * 2)
                    AS Score
            FROM FENQCON c
            LEFT JOIN FENQUIRY q ON q.ENCSUNIQUE = c.ENCONCSUNIQUE
            WHERE c.ENCONEMAIL = "%3$s"
            ORDER BY Score DESC, c.ENCON_ID ASC
            LIMIT 1',
            mysqli_escape_string($connect,$firstname),      // %1
            mysqli_escape_string($connect,$lastname),           // %2
            mysqli_escape_string($connect,$email_address),  // %3
            mysqli_escape_string($connect,$postcode),           // %4
            mysqli_escape_string($connect,$company)         // %5
            );
        $q = mysqli_query($connect,$sql) or die(mysqli_error());

数据正在正确写入 FENQCON 表,但没有写入 FENQUIRY 表。我可以看到这是由于上述查询失败导致 $flag_insert_into_FENQUIRY = true;永远不会跑。

任何 mysqli 专家都可以在这里指出正确的方向吗,因为我看不到代码失败的原因。我在这里阅读了无数关于 mysql 到 mysqli 转换的帖子,我认为我做得对。

【问题讨论】:

在任何地方尝试mysqli_error($connect)。去吧,告诉发生了什么? 您的复制和粘贴是否出错?你说它转换为mysqli的第二部分仍然是mysql @anantkumarsingh FUNCTION ded.levenshtein_ratio 不存在 你是在别的地方调用这个函数吗?我没有看到任何引用ded.levenshtein_ratio 的行;是完整的代码吗? 注意,我看到你在查询变量中转义了很多变量;这对我来说有点奇怪。您是否可以a)在它们进入查询之前将它们转义,或者更好,因为您正在转换为mysqli,将其作为准备好的语句重做? 【参考方案1】:

试试这个...

$q = mysqli_query($connect,$sql) or die(mysqli_error($connect));

更新:

现在您已经解决了上述问题,看来您需要解决将 Levenshtein 库添加到 MySQL 安装的新问题,以便您可以运行 levenshtein_ratio() 函数。这可能会有所帮助:https://samjlevy.com/mysql-levenshtein-and-damerau-levenshtein-udfs/

【讨论】:

这给了我一些奇怪的错误信息 FUNCTION ded.levenshtein_ratio 不存在 我看到它是一个用于查看结果之间相似性的函数。这对 mysqli 查询不起作用是否可行? @StevePrice 你用的是什么版本的 MySQL? 尽快升级。安全漏洞 您安装的 MySQL 可能没有安装 levenshtein 库来运行该功能。这可能会为您提供一些启示:samjlevy.com/mysql-levenshtein-and-damerau-levenshtein-udfs

以上是关于从 mysql 更新到 mysqli 后数据库查询中断的主要内容,如果未能解决你的问题,请参考以下文章

mysqli 更新查询是不是应该返回结果?

更新 WordPress 以使用 mysqli 而不是 mysql

函数内部的mysqli / mysql查询不起作用[重复]

PHP mysqli 子查询返回 Impossible WHERE 在读取 const 表后注意到

php mysql 查询

使用 PHP 和 mysqli 从多个 MySQL 表中获取数据