参数和NULL

时间:2016-09-07 03:51:27

标签: r postgresql

我在使用RPostgres和RPostgreSQL作为INSERT参数查询传递NULL时遇到问题:

在PostgreSQL中:

create table foo (ival int, tval text, bval bytea);

在R:

这有效:

res <- dbSendQuery(con, "INSERT INTO foo VALUES($1, $2, $3)", 
                   params=list(ival=1, 
                               tval= 'not quite null',
                               bval=charToRaw('asdf')
                               )
                    )

但这会引发错误:

res <- dbSendQuery(con, "INSERT INTO foo VALUES($1, $2, $3)",
                   params=list(ival=NULL, 
                               tval= 'not quite null',
                               bval=charToRaw('asdf')
                               )
                   )

使用RPostgres,错误信息为:

  

错误:期待字符串

在RPostgreSQL下,错误是:

Error in postgresqlExecStatement(conn, statement, ...) : 
RS-DBI driver: (could not Retrieve the result : ERROR:  invalid input
syntax for integer: "NULL"
)

代替NA对我来说没问题,但它不是一个解决方案 - 一个字面上的&#39; NA&#39;被写入数据库。

使用例如整数(0)给出相同的&#34;期望一个字符串&#34;消息。

3 个答案:

答案 0 :(得分:3)

这里有一个选项来解决不知道如何在R中表达PostgresSQL pacakge能够成功翻译的NULL值的问题,就是根本不指定你想要的值为{{ 1}}在数据库中。

所以在你的例子中你可以使用它:

NULL

当您希望res <- dbSendQuery(con, "INSERT INTO foo (col2, col3) VALUES($1, $2)", params=list(tval = 'not quite null', bval = charToRaw('asdf') ) ) 拥有col1值时。这当然假设您的表中的NULL可以为空,这可能不是这种情况。

答案 1 :(得分:2)

谢谢大家的帮助。蒂姆的答案很好,我用它来捕捉整数值。我为其余部分采用了不同的路线,在PostgreSQL中编写了一个函数来处理大部分内容。它看起来大致如下:

CREATE OR REPLACE FUNCTION add_stuff(ii integer, tt text, bb bytea)
RETURNS integer
AS
$$
DECLARE
  bb_comp bytea;
  rows    integer;
BEGIN
  bb_comp = convert_to('NA', 'UTF8'); -- my database is in UTF8. 
  -- front-end catches ii is NA; RPostgres blows up 
  -- trying to convert 'NA' to integer.
  tt = nullif(tt, 'NA');
  bb = nullif(bb, bb_comp);
  INSERT INTO foo VALUES (ii, tt, bb);
  GET DIAGNOSTICS rows = ROW_COUNT;
  RETURN rows;
END;
$$
LANGUAGE plpgsql VOLATILE;

现在来看看RPostgres源代码,看看是否有一种简单的方法可以让它更容易处理NULL / NA。希望它失踪,因为没有人想到它,不是因为它超级棘手。 :)

这将导致&#34;错误&#34;回答是否有人试图按字面意思写出&#39; NA&#39;进入数据库并指除NULL / NA以外的其他东西(例如NA =&#34; North America&#34;);鉴于我们的用例,这似乎不太可能。我们会在六个月内看到。

答案 2 :(得分:2)

您可以直接在insert语句中使用NULLIF

res <- dbSendQuery(con, "INSERT INTO foo VALUES(NULLIF($1, 'NULL')::integer, $2, $3)",
                   params=list(ival=NULL, 
                               tval= 'not quite null',
                               bval=charToRaw('asdf')
                               )
                   )

也适用于NA