postgresql 错误:在第1行或其附近有长度为零的分隔标识符:DELETE FROM“区域”WHERE“区域”."”= $1

7gcisfzg  于 2022-11-23  发布在  PostgreSQL
关注(0)|答案(5)|浏览(450)

我使用Rails 4.1和Postgresql(带PG gem)作为我的数据库。我有一个非常稳定的多对多关联,从公司到省份,有一个连接表叫做regions。现在很明显regions表没有主键,因为我使用了{:id =〉false }。但是当我试图使用dependent destroy或者只是简单地调用region对象本身的destroy时,我得到了这个错误:

ERROR:  zero-length delimited identifier at or near """"
 LINE 1: DELETE FROM "regions" WHERE "regions"."" = $1

我知道这个问题是由于regions表缺少主键引起的。奇怪的是,如果我把主键重新添加到表中,destroy工作正常,没有错误。但是,如果我从表中删除主键,错误又回来了。我知道这与postgres有关,但我不知道如何解决这个问题,而不必在regions表中添加主键列。
下面是实际的查询

[DEBUG] [AdminUser Load (0.4ms)  SELECT  "admin_users".* FROM "admin_users"  WHERE "admin_users"."id" = 1  ORDER BY "admin_users"."id" ASC LIMIT 1] (pid:29655)
[DEBUG] [Province Load (0.2ms)  SELECT  "provinces".* FROM "provinces"  WHERE "provinces"."id" = $1 LIMIT 1  [["id", 5]]] (pid:29655)
[DEBUG] [ (0.1ms)  BEGIN] (pid:29655)
[DEBUG] [Region Load (0.3ms)  SELECT "regions".* FROM "regions"  WHERE "regions"."province_id" = $1  [["province_id", 5]]] (pid:29655)
[ERROR] [PG::SyntaxError: ERROR:  zero-length delimited identifier at or near """"
LINE 1: DELETE FROM "regions" WHERE "regions"."" = $1
ki1q1bka

ki1q1bka1#

空字符串应该用单引号而不是双引号,双引号是分隔标识符,“”不是有意义的标识符。
尝试:

WHERE 'regions'.'' = $1

或至少:

WHERE "regions".'' = $1
bogh5gae

bogh5gae2#

请尝试改为设置dependent: :delete_all
示例(不完全确定如何设置多对多关系)。

型号/地区.rb

...
has_many:省份_地区,依赖项::删除全部
has_many:省,通过::省份_地区
...

:destroy/:destroy_all将通过调用相关对象的destroy方法来移除相关对象,因此回调(:before_destroy、:after_destroy等)
:delete/:delete_all将删除关联对象,而不调用其destroy方法。

bqjvbblv

bqjvbblv3#

基于Alex Carol的答案,但完全不同的解决方案。
如果有人这样做:

# models/region.rb
...
has_many :provinces_regions, dependent: :destroy_all
has_many :provinces, through: :provinces_regions
...

并且遇到了这个问题,那么我猜您可能添加了id: false,如下所示:

create_table :provinces_regions, id: false do |t|
  t.belongs_to :regions, index: true
  t.belongs_to :provinces, index: true
end

如果上面的情况属实,那么Rails试图在销毁之前使用id来运行回调。

create_table :provinces_regions do |t|
  t.belongs_to :regions, index: true
  t.belongs_to :provinces, index: true
end

因此,您可以继续使用dependent: :destroy_all,并使用回调和其他需要id的特性。
在此阶段,您需要进行新的迁移来更正它。因此,正如Hussein所提到的,您应该进行迁移:

add_column :provinces_regions, :id, :primary_key

有关详细信息,请参阅here

9o685dep

9o685dep4#

由于这里的答案对我都不起作用,我想我应该包括我的自定义修复。不确定你的用例的翻译是什么,但我希望我的策略的要点是清楚的。
我也在使用自定义主键(uuid)。为了删除连接表上的记录,我跳过了实际删除调用的活动记录,而是使用SQL。

uid = BucketListPhoto.find_by(bucket_list_id: 12, photo_id: 4).uid

deleted_uids = ActiveRecord::Base.connection.execute(
    "DELETE FROM bucket_list_photos WHERE uid='#{uid}' RETURNING uid"
).to_a.map { |record| record['uid'] }

我重写了BucketListPhoto#destroy来使用它。
我也尝试过覆盖BuckerListPhoto::ActiveRecord::Query#destroy_all,但无法成功传递uid数组(用一个查询删除多个uid)。

kxxlusnw

kxxlusnw5#

添加到模型文件:

self.primary_key = :id

相关问题