从CSV导入的PostgreSQL空值为文本-需要空值

从CSV导入的PostgreSQL空值为文本-需要空值,sql,postgresql,table-plus,Sql,Postgresql,Table Plus,我使用phpMyAdmin从MySQL数据库中导出了一堆表(>30)作为CSV文件。这些CSV文件包含NULL值,如: "id","sourceType","name","website","location" "1","non-commercial","John Doe",NULL,"California" 我使用

我使用phpMyAdmin从MySQL数据库中导出了一堆表(>30)作为CSV文件。这些CSV文件包含
NULL
值,如:

"id","sourceType","name","website","location"
"1","non-commercial","John Doe",NULL,"California"
我使用TablePlus将许多这样的csv导入PostgreSQL数据库。但是,列中的
NULL
值实际上显示为文本而不是NULL

当我的应用程序从这些列获取数据时,它实际上检索的是文本
'NULL'
,而不是空值

另外,带有
的SQL命令为NULL
不会检索这些行,可能是因为它们被标识为文本而不是NULL值


是否可以使用SQL命令将所有表中的所有文本
NULL
值转换为实际的NULL值?这将是避免重新导入所有表的最简单方法。

为前来寻找解决方案的人更新 请参见两个潜在解决方案的答案

  • 其中一个解决方案提供了一个SQL COPY方法,该方法必须在导入本身之前执行。解决方案由Michal T提供,并标记为可接受答案,这是从一开始就防止这种情况发生的更好方法
  • 下面我的解决方案在我的应用程序(内置于Laravel/PHP)中使用了一个脚本,可以在导入完成后完成
注意-查看代码中的注释,您可能会在其他语言/框架中找到类似的解决方案

多亏了上面评论中的@BjarniRagnarsson建议,我想出了一个简短的PHP Laravel脚本来对所有列(类型为“string”或“text”)执行更新查询,以将“NULL”文本替换为
NULL

公共函数转换器nullstringtonull()
{
$tables=DB::connection()->getDoctrineSchemaManager()->listTableNames();//获取所有表的列表
$results=[];//存储输出结果的数组
foreach($tables as$table){//遍历每个表
$columnNames=DB::getSchemaBuilder()->getColumnListing($table);//获取所有列的列表
$columnResults=[];//用于存储每列结果的数组
foreach($columnNames as$column){循环遍历每一列
$columnType=DB::getSchemaBuilder()->getColumnType($table,$column);//获取列类型
如果(
$columnType=='string'| |//检查列类型是字符串还是文本
$columnType=='text'
) {
$query=“update”。$table。“set\”“。$column.”\“=NULL,其中\”“。$column.”\“=“NULL”;//按照上面的注释中所述构建更新查询
$r=DB::update($query);//执行更新查询
数组\u推送结果[
$column=>$r
]);//推送列结果
}
}
数组_推送结果[
$table=>$columnResults
]);//推送表格结果
}
dd($results);//输出结果
}

注意:我使用的是Laravel 8。PostgreSQL的
COPY
命令具有
NULL“some_string”
选项,允许将任何字符串指定为NULL值: 这当然需要重新导入所有表

以您的数据为例:

CSV:

"id","sourceType","name","website","location"
"1","non-commercial","John Doe",NULL,"California"
"2","non-commercial","John Doe",NULL,"California"
下表:

CREATE TABLE import_with_null(id integer,source_type varchar(50),name varchar(50),website varchar(50),location varchar(50));
COPY
语句:

从“/tmp/import_with_null.csv”复制带有_null(id、源类型、名称、网站、位置)的导入_,格式为(csv,null'null',标题);
将空字符串正确导入为SQL NULL的测试:

在网站为空的情况下,从带有空值的导入中选择*;

将空字符串转换为SQL空值的重要部分是
NULL'NULL'
,可以是任何其他值
NULL'whatever string'

可以编写一个简单的脚本来读取CSV并插入到表中吗?我的问题更多的是在导入完成后要做什么。问题是为什么会出现空值字段而不是空(null)字段。除非你需要经常这样做,最简单的解决方案是导入到一个临时表中,该列定义为文本,然后通过适当的转换选择到最终表中。@BjarniRagnarsson您能提供一个示例作为解决方案吗?一种方法是在选择到最终表中时使用NULLIF函数将NULL字符串转换为NULL。实际上-在这种情况下,您可以直接读取最终的表并运行
updatetablesetwebsite=null,其中website='null'因为它是一个文本列,NULL不会导致错误。请用示例详细说明。如果你能展示完整的示例来帮助任何可能再次面临此问题的人,我想我会将此标记为一个答案,因为我上面的答案非常特定于应用程序(需要laravel和php)。用你的数据添加了一个完整的示例。
 id |  source_type   |   name   | website |  location  
----+----------------+----------+---------+------------
  1 | non-commercial | John Doe |         | California
  2 | non-commercial | John Doe |         | California
(2 rows)