【问题标题】:Python/MySQL How to insert a String using a variable, keeps changing "TRUE" to 1Python / MySQL如何使用变量插入字符串,不断将“TRUE”更改为1
【发布时间】:2019-05-28 19:33:22
【问题描述】:

我有一个名为 led_status 的表和一个名为“test_led”的字段:

mysql> describe led_status;
+------------------------------+------------+------+-----+---------+-------+
| Field                        | Type       | Null | Key | Default | Extra |
+------------------------------+------------+------+-----+---------+-------+
| test_led                     | varchar(5) | NO   |     | NULL    |       |
+------------------------------+------------+------+-----+---------+-------+

我正在尝试使用以下代码输入“TRUE”或“FALSE”(不是 int 1 或 0)字符串:

def write_database_value(table,field,value):
    connect = mysql.connector.connect(user=db_info.username,
                              password=db_info.password,
                              host=db_info.servername,
                              database=db_info.database)
    cursor = connect.cursor()
    cursor.execute(("UPDATE %s SET %s = %s") % (table, field, value))
    connect.commit()
    cursor.close()
    connect.close()

def read_database_value(table,field):
    connect = mysql.connector.connect(user=db_info.username,
                              password=db_info.password,
                              host=db_info.servername,
                              database=db_info.database)
    cursor = connect.cursor(buffered=True)
    cursor.execute(("SELECT %s FROM %s") % (field, table))

    for data in cursor:
        database_value = data
        cursor.close()
    connect.close()
    return database_value

从这个脚本中调用:

def get_led_status(led):
    led_status = read_database_value("led_status", led)
    led_status = (led_status[0])
    return led_status

def is_pool_pump_running():
    pool_running = get_led_status("test_led")
    if pool_running == "TRUE":
        print("Pool Pump is Running, shutting it off now")
        write_database_value("led_status","test_led","FALSE")
    else:
        print("Pool Pump is NOT Running, turning it on now")
        write_database_value("led_status","test_led","TRUE")

但是,每次我运行脚本时,它都会将我的“TRUE”更改为 1,将“FALSE”更改为 0。

我正在从平面文件切换到数据库,并且我的所有代码(到目前为止 4000 行)都使用“TRUE”和“FALSE”,所以我真的不想为了使用而重写它1 和 0,而不是“TRUE”和“FALSE”。

任何想法将不胜感激。

【问题讨论】:

  • 两个重要的事情:(1)你没有在SQL上使用%字符串格式,它会导致SQL注入漏洞(2)划分数据及其表示:0/@987654327 @ 或 Python 中的 False/True 是用于在计算机中存储和处理的数据,字符串 "TRUE""FALSE" 是您将其呈现给人类的方式。
  • 谢谢@KlausD。我的理解是 %s 正确的方法,并且 cursor.execute 专门防止 SQL 注入问题。 Stack Exchange 上的Posts 为我指明了这个方向。这些信息不正确吗?其次,正如我上面所说,我正在从一个使用真/假表示的平面文件迁移,当我迁移到数据库设计时,我真的不想将所有代码重写为 0/1,因此我想坚持将 true/false 作为 varchar 而不是 0/1 作为 bit 或 tinyint。
  • 重要的区别是字符串和参数之间的%。必须是逗号才能安全。
  • @KlausD。啊!!!我想错了%!我会详细阅读并更改它。

标签: python mysql


【解决方案1】:

MySQL 没有布尔类型(真/假),它们被自动解释(并存储)为 0/1(在上面的模式中,您甚至明确声明您需要 tinyint,而不是常规的 32 位整数)。 Nothing you can do about that!

如果要存储文字值“TRUE”/“FALSE”,则应使用 varchar(5) 类型的列。

附注:这些列的默认值应该是 0 或 1,或者它应该可以为空 - 您已将它们的默认值设置为 NULL 并且该列不可为空,这可能会导致错误。

【讨论】:

  • 我使用的是 varchar(5)!如果你看我上面的表格,test_led 是 varchar(5) 类型。
  • @Richard 在我写这个答案的时候你不在。它显示在您帖子的修订中...
  • 实际上 test_led 总是一个 varchar(5)。还是不行。
  • def get_led_status(led): led_status = read_database_value("led_status", led) led_status = (led_status[0]) return led_status
  • 抱歉,不确定如何在评论中格式化代码 :-)
【解决方案2】:

正如@frsechet 回答所指出的,在 SQL 中,您只有 0/1 表示布尔值。如果您想要 TRUE/FALSE 字符串,则需要将列类型更改为 string/char(5)。

其他选项是,如果您使用通用函数来获取/更新列值,那么您可以在该函数内定义值映射,将 TRUE/FALSE 转换为 1/0,反之亦然。

【讨论】:

  • 我使用的是 varchar(5)!如果你看我上面的表格,test_led 是 varchar(5) 类型。
【解决方案3】:

感谢所有提供意见的人。经过 LOT 的挖掘,我发现了我的问题。显然,您不能在准备好的语句中参数化表名,这正是我在上面尝试做的。 POST where I found the answer @Conspicuous Compiler 对那句话很执着。

问题出在我的write_database_value() 函数中。这是根据需要工作的正确函数:

def write_database_value(table,column,value):
    try:
        connection = mysql.connector.connect(user=db_info.username,
                                      password=db_info.password,
                                      host=db_info.servername,
                                      database=db_info.database)
        cursor = connection.cursor(buffered=True)
        sql_update = "UPDATE " + table + " SET " + column + " = %s"
        cursor.execute(sql_update, (value,))
        connection.commit()
        cursor.close()
        connection.close()
    except Error as error :
        print("Failed to Update record in database: {}".format(error))
    finally:
        if(connection.is_connected()):
            connection.close

重大变化:

来自: cursor.execute(("UPDATE %s SET %s = %s") % (table, field, value))

到这里:

sql_update = "UPDATE " + table + " SET " + column + " = %s"
cursor.execute(sql_update, (value,))

【讨论】:

  • 今天早上阅读您的代码时,我 100% 会说,这是您自己弄清楚的道具。正如我的答案中的链接中所述,无论字母大小写为 TRUE,都将转换为 1。您的查询是“UPDATE led_status SET TRUE”,读作 1,而不是字符串“TRUE”,因为它没有用引号括起来. “从 led_status 中选择 test_led”可以帮助您更快地进行调试。旁注:建议使用准备好的语句,而不是在查询中插入字符串,出于安全原因,也出于您在这里遇到的原因。
  • 示例:如果有人写了一些类似“1; drop database;”的东西而不是“true”...
猜你喜欢
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多