根据我是在“一体式”查询中运行查询还是单独运行它们,我会得到不同的响应。
我一生都无法弄清楚我做错了什么。
代码:
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 上运行此程序,但考虑到“一体化”的效果,我认为这不相关。
像往常一样,我会回答我自己的问题。
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
循环是多余的,因为结果已经是元组列表。