0

我想用 ruby​​ 的默认 CSV 库编写一个 CSV,以便使用 MySQL 的快速导入 LOAD DATA INFILE。

目前,当我为一个字段输入 nil 时,它写为...;;...,而不是我希望它是...;\N;...(大写 N 表示 NULL,不要与 \n 换行符混淆)。

CSV.open(product_updates_file_name, "wb", {col_sep: ";", headers: false, force_quotes: false}) do |product_csv|
    product_csv << ["foo", nil, "bar"]
end

它目前导致十进制字段在数据库中加载为 0.00 而不是 NULL。

我知道,之后我可以将其设置为 NULL,但是有数百万行和几列受到影响,所以我强烈希望按照 MySQL 的预期编写 CSV:

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

4

2 回答 2

0

You could modify the CSV-methods:

require 'csv'
class Array
  alias :old_to_csv :to_csv
  #Extend to_csv for usage like ["foo", nil, "bar"].to_csv( :col_sep => ";")
  def to_csv(options)
    self.map{|s| s.nil? ? '\N' : s }.old_to_csv 
  end
end  

class CSV
  alias :old_push :<<
  def <<(data)
    case data
      when Array
        old_push data.map{|s| s.nil? ? '\N' : s }
      else
        old_push data
      end
  end
end

#Testcode:
puts ["foo", nil, "bar"].to_csv( :col_sep => ";")   #--> [["foo", "\\N", "bar"]]
CSV.open('test.csv', "wb", 
      {col_sep: ";", headers: false, force_quotes: false }
  ) do |product_csv|     
    product_csv << ["foo", nil, "bar"] 
end 
#-> Creates test.csv with 'foo;\N;bar'

This works only, if you insert Arrays. If you insert other stuff, you must modify the logic.


Remark: My first idea was to use a converter. But it worked only for parsing a csv, not for writing.

CSV::Converters[:nil_N] = lambda{|s| 
  s.nil? ? '\N' : s
}
p CSV.parse('foo;;bar', :col_sep => ";",  :converters => :nil_N)
#-> [["foo", "\\N", "bar"]]

Perhaps somebody else knows a way to use converters to build csv-files.

于 2012-08-29T12:05:15.960 回答
0

尝试像这样覆盖nil'sto_s方法:

class << nil
  def to_s
    "my nil placeholder text"
  end
end

所有使用的代码to_s都将使用此实现作为值 nil。

于 2012-08-29T10:35:02.720 回答