Python MySQL:拆分查询出现意外响应

问题描述 投票:0回答:1

根据我是在“一体式”查询中运行查询还是单独运行它们,我会得到不同的响应。

我一生都无法弄清楚我做错了什么。

代码:

import mysql.connector


def all_in_one():
    try:
        conn = mysql.connector.connect(
            host="localhost", user="fanw", password="secret", database="fanw"
        )

        cursor = conn.cursor()

        query = """
            CREATE TEMPORARY TABLE IF NOT EXISTS temp_pairs AS

            SELECT
                fd.nid,
                fd.title
            FROM
                node__field_card_display cl
            JOIN 
                node_field_data fd ON cl.entity_id = fd.nid AND cl.langcode = fd.langcode
            WHERE
                cl.field_card_display_target_id = 2049
                AND cl.langcode = 'en'
                AND cl.bundle = 'person';

            SELECT
                t.entity_id
            FROM
                node__body AS t
            JOIN
                temp_pairs AS tp ON BINARY t.body_value LIKE CONCAT('%', tp.title, '%') 
                AND NOT (t.body_value LIKE CONCAT('%', tp.nid, '">', tp.title, '<', '%'))
            WHERE
                t.body_format <> 'plain_text'
                AND t.entity_id <> tp.nid;
        """
        for each in cursor.execute(query, multi=True):
            result = each.fetchall()
            print(len(result))

        conn.commit()

    except Exception as e:
        # Handle any errors and potentially roll back the transaction
        conn.rollback()
        print(f"Error: {str(e)}")

    finally:
        cursor.close()
        conn.close()


def separate():
    try:
        conn = mysql.connector.connect(
            host="localhost", user="fanw", password="secret", database="fanw"
        )
        cursor = conn.cursor()

        query = """
            SELECT
                fd.nid,
                fd.title
            FROM
                node__field_card_display cl
            JOIN 
                node_field_data fd ON cl.entity_id = fd.nid AND cl.langcode = fd.langcode
            WHERE
                cl.field_card_display_target_id = 2049
                AND cl.langcode = 'en'
                AND cl.bundle = 'person';
        """
        cursor.execute(query)
        result = cursor.fetchall()
        people = []
        for person in result:
            nid, name = person
            people.append((nid, name))

        cursor.execute(
            "CREATE TEMPORARY TABLE IF NOT EXISTS temp_pairs (nid INT(10) unsigned, title VARCHAR(255));"
        )
        cursor.executemany(
            "INSERT INTO temp_pairs (nid, title) VALUES (%s, %s);", people
        )

        query = f"""
            SELECT
                t.entity_id
            FROM
                node__body AS t
            JOIN
                temp_pairs AS tp ON BINARY t.body_value LIKE CONCAT('%', tp.title, '%') 
                AND NOT (t.body_value LIKE CONCAT('%', tp.nid, '">', tp.title, '<', '%'))
            WHERE
                t.body_format <> 'plain_text'
                AND t.entity_id <> tp.nid;
        """
        cursor.execute(query)
        result = cursor.fetchall()
        print(len(result))

        conn.commit()

    except Exception as e:
        # Handle any errors and potentially roll back the transaction
        conn.rollback()
        print(f"Error: {str(e)}")

    finally:
        cursor.close()
        conn.close()


if __name__ == "__main__":
    print("All in one: ")
    all_in_one()

    print("Separate:")
    separate()
    print("DONE!")

运行代码给出:

❯ python3 migrate.py                     
All in one: 
0
96
Separate:
0
DONE!

我希望“单独”查询也给出 96

我已经尝试了

mysql-connector-python==8.3.0
PyMySQL==1.1.0

我在 mysql CLI 和使用 DBeaver 中运行了“一体化”查询,两者都给了我96

我在 MacBook Pro M1 上运行此程序,但考虑到“一体化”的效果,我认为这不相关。

python mysql mysql-connector pymysql mysql-connector-python
1个回答
0
投票

像往常一样,我会回答我自己的问题。

tl;dr: 这是字符集(也可能是排序规则)。

因此,当您执行“CREATE TEMPORARY TABLE … AS”时,它将从 SELECT 语句继承这些设置。

在这种情况下

utf8mb4
(和
utf8mb4_general_ci
)。

但是,如果您执行“独立”“CREATE TEMPORARY TABLE”(如在

separate
函数中),该表将继承 database 默认值,在本例中为 latin1,因为
temp_pairs
表包含人名来自世界各地的用户,如果他们的名字中包含
latin1
字符集之外的字符,则查询不会拾取该字符。

所以正确的查询是:

CREATE TEMPORARY TABLE IF NOT EXISTS
temp_pairs
(
  nid INT(10) unsigned NOT NULL, title VARCHAR(255) NOT NULL
) ENGINE=InnoDB CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';

作为旁注,

for person in result
循环是多余的,因为结果已经是元组列表。

© www.soinside.com 2019 - 2024. All rights reserved.