在 Mysql table RMySQL 中插入 NA 值

Insert NA values in Mysql table RMySQL

我试图在 mysql table 中插入一个数据框行,但我在字符和数字列中有 NA 值。我收到此错误: .local(conn, statement, ...) 错误: 无法 运行 语句:'field list'

中的未知列 'NA'

这是我的查询:

sql <- sprintf("insert into payment (amount,payment_type,date,customer_total,base_price, p2c_total, partner_total, pay_online, pay_at_lot,tax,first_name_on_card,last_name_on_card,address)
                  values (%f, %d, '%s',%f,%f,%f,%f,%f,%f,%f,'%s','%s','%s');",
                 payments[i,]$amount,payments[i,]$payment_type,payments[i,]$date, payments[i,]$customer_total,
                 payments[i,]$base_price, payments[i,]$p2c_total, payments[i,]$partner_total,
                 payments[i,]$pay_online,payments[i,]$pay_at_lot,payments[i,]$tax,
                 payments[i,]$first_name_on_card, payments[i,]$last_name_on_card, payments[i,]$address)
rs <- dbSendQuery(db, sql[i])
dbClearResult(rs)
    

这是 sql 代码:

insert into reservation (reservation_number, driver_name, number_passengers, checkin_datetime, checkout_datetime, days, reservation_date, reservation_email,id_reservation_status, id_payment, id_ship, id_facility, id_user) values ('j990j','CB', 4, '2020-01-12 10:00:00', '2020-01-19 10:30:00', 8, 'NA', 'cb@gmail.com',NA, 1, 2, 547, 6);

这是 mysql 错误: #1054 - La columna 'NA' en field list es desconocida

MySQL版本:8.0.27

R 版本:4.03

RMySQL 包:0.10.22

将您的 NA 换成 'NA'

insert into reservation (reservation_number, driver_name, number_passengers, checkin_datetime, checkout_datetime, days, reservation_date, reservation_email,id_reservation_status, id_payment, id_ship, id_facility, id_user) values ('j990j','CB', 4, '2020-01-12 10:00:00', '2020-01-19 10:30:00', 8, 'NA', 'cb@gmail.com','NA', 1, 2, 547, 6);

三种方式来看待这个问题:

  1. 不要sprintf/paste数据到查询字符串中。除了 malicious SQL injection (e.g., XKCD's Exploits of a Mom aka "Little Bobby Tables") 的安全问题外,它还涉及格式错误的字符串或 Unicode-vs-ANSI 错误,即使它是一个数据分析师 运行 查询。

    方便的是,有一个函数负责以更安全的方式将数据从 data.frame 插入 table:dbAppendTable。你也许可以做到

    dbAppendTable(db, "payment", payments[i,])
    

    如果需要插入所有列,否则需要更详细的内容:

    dbAppendTable(db, "payment", payments[i,c("amount", "payment_type", "date", "customer_total", "base_price", "p2c_total", "partner_total", "pay_online", "pay_at_lot", "tax", "first_name_on_card", "last_name_on_card", "address")])
    

    如果您计划对超过 1 行执行此操作,那么 dbAppendTable 可以毫无问题地处理多行。

  2. 如果你真的想用你自己的 insert 语句一次做一行,那么我强烈建议你使用参数化查询,也许是这样的:

    qry <- "insert into payment (amount,payment_type,date,customer_total,base_price, p2c_total, partner_total, pay_online, pay_at_lot,tax,first_name_on_card,last_name_on_card,address)
                      values (?, ?, ?,?,?,?,?,?,?,?,?,?,?);"
    dbExecute(db, qry, params = payments[i, c("amount", "payment_type", ...)])
    

    (这让我想起了......dbExecute 是一个很好的包装器,它确实 dbSendStatement 总是跟在 dbClearResult 之后。还有 dbGetQuery 这实际上是 dbSendQuery 总是后跟 dbClearResult,返回数据。您不会从 table 返回行,所以无论如何第一个是首选。)

    注意:此功能需要 up-to-date 驱动程序来访问数据库。如果您使用 RMySQL 那么就会有一个问题:该包多年来(截至目前)没有看到实质性更新,并且不支持参数化查询。我相信 RMariaDB 包与 MySQL 完全兼容,它支持参数化查询。

  3. 如果你真的必须手动执行此操作(真的,我强烈反对,太多次我认为我可以解决风险,但每次都被咬),那么 R 的 NA 翻译成 null(没有引号!)。为此,您需要有条件地添加引号。类似于:

    ifelse(is.na(payments[i,]$date), "null", sQuote(payments[i,]$date))
    

    for each string-like 字段,并确保将格式中的 '%s' 更改为 %s。几乎可以肯定有更好的方法可以自动执行此操作,这样您就不会输入一打或更多 ifelse,但在我看来,这样做确实不值得。

    (如果您依赖 sprintf("%s", ..) 的不同语义与 sQuote 的隐式 string-ification,那么您可能需要更多 elbow-grease。)