2
votes

Insérer dans MySQL à partir de R

J'utilise le package DBI pour insérer des données dans MySQL. Voici le 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)
}

Le problème est dans la colonne 3td, qui est numérique, mais qui a des valeurs NA . Quand la boucle arrive à la ligne qui a la valeur NA , elle renvoie une erreur:

Erreur dans .local (conn, instruction, ...): impossible d'exécuter l'instruction: Colonne inconnue "NA" dans "liste de champs"

J'ai essayé de changer NA en NaN, "NULL" et quelques autres types, mais rien ne fonctionne. Si je change NA en 0, cela fonctionne.


2 commentaires

Vérifiez si la 3ème colonne est égale à NA et convertissez-la en 0 si c'est le cas.


Btw, il semble y avoir un guillemet simple supplémentaire avant la fermeture)


3 Réponses :


0
votes

Si vous êtes à l'aise de changer NA en 0, le mieux est de faire ce qui suit.

test [is.na (test)] <- 0

Cela remplacera tous les NA du test data.frame par 0. Vous pouvez faire de même et changer la chaîne «NULL» si vous le souhaitez également.

test [is.na (test)] <- 'NULL'

Si vous souhaitez remplacer une seule colonne, vous pouvez effectuer les opérations suivantes:

test $ col3 [is.na (test $ col3)] <- 0


3 commentaires

Je ne veux pas mettre NA à zéro car je ne sais pas lesquels valent 0 et quel Na.


Remplacer par la chaîne 'NULL'


Pour les NA , ils veulent que la sous-chaîne NULL soit dans la chaîne de requête entre les virgules VALUES . Pas 'NULL' .



1
votes

Tenez compte de la norme de paramétrage de l'industrie de la programmation pour toute couche d'application telle que R qui exécute SQL. Avec cette approche, vous évitez tout besoin d'interpolation de chaîne ou de cotes compliquées. La norme DBI de R a plusieurs façons, dont l'une est 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)
}


3 commentaires

J'ai essayé votre code, mais il renvoie une erreur: `Erreur dans .local (conn, instruction, ...): impossible d'exécuter l'instruction: vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à votre version de serveur MySQL pour la bonne syntaxe à utiliser près de '101.2, 101.2, `0.05, 101.2, 101.2, 101.2, 101.2, 250000, 253000, 02.01.2008)' à la ligne 1`


Après avoir changé "" en NA, il y a des problèmes avec les points à l'intérieur des caractères: Erreur dans .local (conn, instruction, ...): impossible d'exécuter l'instruction: Vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à votre version de serveur MySQL pour la bonne syntaxe à utiliser près de '.2008)' à la ligne 2


Il semble que vous ayez plus de 4 colonnes dans trade_data que cet INSERT suppose si vous omettez des colonnes explicites. Assurez-vous d'inclure toutes les colonnes dont vous avez l'intention de mettre à jour les données: INSERT INTO trade_data (Col1, Col2, Col3, ...) VALUES (...



0
votes

J'ai bien compris. J'ai dû changer "" en "NULL" et NA en NULL, puis j'ai utilisé l'instruction ifelse dans insert. Comme ceci:

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)


1 commentaires

Votre question ne mentionne pas que les chaînes vides deviennent des valeurs nulles. En SQL, la chaîne vide n'est pas nulle. (Seul Oracle assimile la chaîne vide à null, ce n'est pas du SQL standard.)