“错误:整数的输入语法无效:”在 Redshift 表中为 SMALLINT 列插入 NULL 值时?

Posted

技术标签:

【中文标题】“错误:整数的输入语法无效:”在 Redshift 表中为 SMALLINT 列插入 NULL 值时?【英文标题】:"Error: invalid input syntax for integer:" when inserting NULL values for an SMALLINT column in a Redshift table? 【发布时间】:2017-11-27 23:08:54 【问题描述】:

我有这个本地定义的 python 函数,在将数据插入红移表时可以正常工作:

def _insert_data(table_name, values_list):
    insert_base_sql = f"INSERT INTO table_name VALUES"
    insert_sql = insert_base_sql + ','.join([str(row) for row in values_list])
    <run_local_python_code_to_execute_insert_sql>

values_list 是一个元组列表,每个元组的元素数量与table_name 中的列数相同(尽管我没有在此函数中明确断言/检查)。但是,我找不到为smallint 列插入NULL 值的方法。这是相关表的架构(在创建表时没有为列分配 DEFAULT 值):

 schemaname |      tablename      |    column    |         type          | encoding | distkey | sortkey | notnull
------------+---------------------+--------------+-----------------------+----------+---------+---------+---------
 public     | table               | col1         | bigint                | lzo      | t       |       1 | f
 public     | table               | col2         | date                  | lzo      | f       |       2 | f
 public     | table               | col3         | smallint              | lzo      | f       |       3 | f
 public     | table               | col4         | smallint              | lzo      | f       |       4 | f
 public     | table               | col5         | double precision      | none     | f       |       0 | f
 public     | table               | col6         | bigint                | lzo      | f       |       0 | f
 public     | table               | col7         | character varying(48) | bytedict | f       |       0 | f

我特别想为col3col4 插入NULL 值;我尝试使用 '''NULL' 创建元组,但遇到此错误:Error: invalid input syntax for integer: "NULL"

对于它的价值,这就是 INSERT 语句中清理后的行最终的样子:('bigint_value', 'dt_value', 'NULL', 'NULL', 'double_value', 'bigint_value', 'string_name')

【问题讨论】:

您是否尝试在您希望NULLs 所在的位置使用None 的值? 是的——这也是我的第一个想法;导致此错误:Error: column "none" does not exist in table_name(行看起来像('bigint_value', 'dt_value', None, None, 'double_value', 'bigint_value', 'string_name') 要插入空值,请使用不带引号的关键字 NULL。 是的-@alecxe 下面的回答有所帮助。远离','.join([str(row) for row in values_list]) 并改用占位符。 【参考方案1】:

您所采取的方法本身就很危险。使用字符串连接和格式化构造查询容易出错且不安全——您的查询容易受到SQL injection attacks 的攻击。

相反,正确参数化您的查询,将参数列表作为单独的参数传递给cursor.executemany()。这是生成占位符的一种,不是很漂亮的方法:

placeholders = ", ".join(["%s"] * len(values_list))
query = f"""
    INSERT INTO 
        table_name 
    VALUES
        (placeholders)
"""
cursor.executemany(query, values_list)

(注意表名不能参数化 - 单独清理和验证)

注意executemany() 的使用——它将为values_list 中的每个元组执行准备好的查询语句。

但是,如果您使用的是 psycopg2,还有一种更好的方法可以将多条记录插入到表中 - execute_values() - 看看 this answer。

并且,回到您最初的问题 - 如果您采用这种方法,None 占位符值将被数据库驱动程序自动转换为 'NULL' 字符串

【讨论】:

注意:sql注入问题;我会纠正的。我最初也尝试使用None,但遇到了这个错误:Error: column "none" does not exist in table_name @ScottBorden 对,我怀疑您没有使用参数化查询, None 被插入到查询中作为 None "keyword" 没有引号 - 因此它被解释为列名而不是列值。请尝试这种方法。

以上是关于“错误:整数的输入语法无效:”在 Redshift 表中为 SMALLINT 列插入 NULL 值时?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在redshift中创建表需要很多时间?

AWS 在 VPC 中访问 Redshift

Redshift - 提取约束

无法在 AWS 胶水中建立 Redshift 连接,其中 Redshift 位于不同的位置 (us-west-1)

Redshift卡在调整大小模式?

在 Redshift 中检查用户的“连接限制”