问题
I am using DBI package to insert data to MySQL. Here is the code:
ch <- DBI::dbConnect(MySQL())
dbSendQuery(ch, 'set character set "utf8"')
dbSendQuery(ch, 'SET NAMES utf8')
for (i in 1:nrow(test)) {
query <- paste0("INSERT INTO trade_data VALUES('0', '", test[i, 1], "', '",
test[i, 2], "', ", test[i, 3], "')")
dbSendQuery(ch, query)
}
The problem is in 3td column, which is numeric, but have NA
values. When loop comes to row which has NA
value it returns an error:
Error in .local(conn, statement, ...) : could not run statement: Unknown column 'NA' in 'field list'
I tried to change NA to NaN, "NULL", and some other types, but nothing works. If I change NA to 0 it works.
回答1:
Consider the programming industry standard of parameterization for any application layer like R that runs SQL. With this approach, you avoid any needs of string interpolation or messy quote enclosures. R's DBI standard has several ways, one of which is sqlInterpolate:
# PREPARED STATEMENT (NO DATA) QMARKS REQUIRED BUT NAMES CAN CHANGE
sql <- "INSERT INTO trade_data (Col1, Col2, Col3, col4)
VALUES (?param1, ?param2, ?param3, ?param4)"
ch <- DBI::dbConnect(MySQL())
dbSendQuery(ch, 'set character set "utf8"')
dbSendQuery(ch, 'SET NAMES utf8')
for (i in 1:nrow(test)) {
# BIND PARAMS
query <- sqlInterpolate(conn, sql, param1 = "0", param2 = test[i, 1],
param3 = test[i, 2], param4 = test[i, 3])
# EXECUTE QUERY
dbSendQuery(ch, query)
}
回答2:
If you are comfortable changing NA to 0, then your best bet is to do the following.
test[is.na(test)] <- 0
This will replace all NAs in the data.frame test
with 0. You can do the same and change to string 'NULL' if you please as well.
test[is.na(test)] <- 'NULL'
If you are looking to replace only a column, you can do the following:
test$col3[is.na(test$col3)] <- 0
回答3:
I got it right. I had to change "" to "NULL" and NA to NULL, and then used ifelse statement in insert. Like this:
ch <- DBI::dbConnect(MySQL())
dbSendQuery(ch, 'set character set "utf8"')
dbSendQuery(ch, 'SET NAMES utf8')
test[test == ""] <- "NULL"
test[is.na(test)] <- "NULL"
for (i in 1:nrow(test)) {
query <- paste0("INSERT INTO trade_data VALUES('0', '", test[i, 1], "', ",
ifelse(test[i, 2] == "NULL", test[i, 2], paste0("'", test[i, 2], "'")), ", ",
ifelse(test[i, 3] == "NULL", test[i, 3], paste0("'", test[i, 3], "'")), ", ",
# test[i, 3],", ",
test[i, 4], ", ",
test[i, 5], ", ",
test[i, 6], ", ", test[i, 7] , ", ",
test[i, 8], ", ", test[i, 9] , ", ",
test[i, 10], ", ", test[i, 11] , ", '",
test[i, 12], "')")
dbSendQuery(ch, query)
}
DBI::dbDisconnect(ch)
来源:https://stackoverflow.com/questions/54715579/insert-into-mysql-from-r