在创建模特交易时,我使用after_create在DealPrize表上创建奖品。
Deal和DealPrize属于/ has_many关系:a Deal有许多Deal奖品,Dealprize属于Deal。
它的工作原理如下:内部交易,我有一个专栏'奖品编号'我使用了一个after_create,以便amdin创建一个新的交易,应用程序获取这个prize_number列,并在DealPrize表中创建这一批奖品(根据需要插入尽可能多的行)。
为了表现,奖品的数量可以是> 500,000并且为了优化INSERT。
我找到https://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/:我选择了选项2(原始SQL和usi_ng'交易')。事实上,最有效的方式(选项3:'单个质量插入')在piostgresql中不容易获得(该人提供SQL的exmaples)并且对于mee来说太难了(它涉及一些COPY命令。 ..)。
所以这是优化前的代码(工作原理)
模型/ deals.rb
after_create :create_deal_prizes
def create_deal_prizes
self.prizes_number.times do
prizes = DealPrize.create(:deal_id => self.id, :admin_user_id => self.admin_user_id)
prizes.save
end
end
所以我无法在PostgreSQL中应用选项2(带有事务的原始SQL),如this guy for SQL
下面'我尝试了什么:
模型/ deals.rb
after_create :create_deal_prizes
def create_deal_prizes
Deal.transaction do
self.prizes_number.times do |i|
DealPrize.connection.execute "INSERT INTO ‘deal_prizes’ (deal_id) values (self.deal.id)"
end
end
end
但它失败了,我收到了错误:
ERROR: relation "‘deal_prizes’" does not exist LINE 1: INSERT INTO ‘click_win_throbbers’ (deal_id)
顺便说一句,我也试过INSERT INTO'dealprizes',INSERT INTO'DealDePrize'它也不起作用。
如何使用PostgreSQL执行此操作?
感谢您的帮助
修改 我试过了
def create_deal_prizes
Deal.transaction do
values = (0..prize_number).to_a.map{|x| "(#{x}),"}.join.chomp(",")
ActiveRecord::Base.connection.execute "INSERT INTO deal_prizes (deal_id, created_at, updated_at) values ( (#{values}), ('2009-01-23 20:21:13'), ('2009-01-23 20:21:13') )"
end
end
我收到此错误:
ERROR: column "deal_id" is of type integer but expression is of type record
PG::SyntaxError - ERROR: INSERT has more expressions than target columns
LINE 1: ...id, created_at, updated_at) values ( (0),(1),(2),(3),(4),(5)..
除了必须放入每个新的deal_prizes行的deal_id是相同的:它总是这个单一游戏的id:我不会赢得每一行deal_prizes不同的deal_id(如这里(1),(2)......
这是原始SQL
SELECT 1 AS one FROM "deals" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "deals"."id" AND "friendly_id_slugs"."sluggable_type" = $1 WHERE ("deals"."id" IS NOT NULL) AND ("friendly_id_slugs"."sluggable_type" = 'Deal' AND "friendly_id_slugs"."slug" = 'zazzaza') LIMIT 1 [["sluggable_type", "Deal"]]
SQL (0.5ms) INSERT INTO "deals" ("deal_main_goal", "deal_population_target_age", "deal_population_target_egroup", "deal_campaign_code", "country", "title", "description", "twitter_msg", "image_url", "deal_project_management_url", "client_contact_point_name", "client_contact_point_profile_url", "hp_image_alt", "rules_url", "deal_population_target_gender", "contact_for_prizes_full_name", "contact_for_prizes_email", "contact_for_prizes_how_to_contact_details", "contact_for_prizes_crm_profile_url", "click_to_win_throbber_per_deal_qty", "admin_user_id", "slug", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24) RETURNING "id" [["deal_main_goal", "{}"], ["deal_population_target_age", "{}"], ["deal_population_target_egroup", "{}"], ["deal_campaign_code", ""], ["country", "Armenia"], ["title", "zazzaza"], ["description", ""], ["twitter_msg", ""], ["image_url", ""], ["deal_project_management_url", ""], ["client_contact_point_name", ""], ["client_contact_point_profile_url", ""], ["hp_image_alt", ""], ["rules_url", ""], ["deal_population_target_gender", ""], ["contact_for_prizes_full_name", ""], ["contact_for_prizes_email", ""], ["contact_for_prizes_how_to_contact_details", ""], ["contact_for_prizes_crm_profile_url", ""], ["prize_number", 7], ["admin_user_id", 1], ["slug", "zazzaza"], ["created_at", "2015-09-04 21:21:41.157857"], ["updated_at", "2015-09-04 21:21:41.157857"]]
(1.6ms) INSERT INTO deal_prizes (deal_id, created_at, updated_at) values ( ((0),(1),(2),(3),(4),(5),(6),(7)), ('2009-01-23 20:21:13'), ('2009-01-23 20:21:13') )
PG::DatatypeMismatch: ERROR: column "deal_id" is of type integer but expression is of type record
LINE 1: ...obbers (deal_id, created_at, updated_at) values ( ((0),(1),(...
^
HINT: You will need to rewrite or cast the expression.
: INSERT INTO deal_prizes (deal_id, created_at, updated_at) values ( ((0),(1),(2),(3),(4),(5),(6),(7)), ('2009-01-23 20:21:13'), ('2009-01-23 20:21:13') )
(1.8ms) ROLLBACK
Completed 500 Internal Server Error in 605ms
PG::DatatypeMismatch - ERROR: column "deal_id" is of type integer but expression is of type record
答案 0 :(得分:1)
好像你的代码中有拼写错误。连接应为ActiveRecord::Base.connection
,但您写了DealPrize.connection.execute
。
connection = ActiveRecord::Base.connection
connection.execute "sql query"
尝试更改您的代码,例如
after_create :create_deal_prizes
def create_deal_prizes
Deal.transaction do
connection = ActiveRecord::Base.connection
self.prizes_number.times do |i|
connection.execute "INSERT INTO ‘deal_prizes’ (deal_id) values (self.deal.id)"
end
end
end
答案 1 :(得分:0)
如何制作一些表演。而不是执行n次原始SQL,你可以只进行一次长查询。感谢@Dipak找到错字
after_create :create_deal_prizes
def create_deal_prizes
Deal.transaction do
values = (0..prizes_number).to_a.map{|x| "(#{x}),"}.join.chomp(",")
ActiveRecord::Base.connection.execute "INSERT INTO deal_prizes (deal_id) values #{values}"
end
end
那给了我
"INSERT INTO deal_prizes (deal_id) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),(50)"