【问题标题】:How can I fix "operator does not exist: text = uuid" when using Haskell's postgres-simple library to perform a multi-row insert?使用 Haskell 的 postgres-simple 库执行多行插入时,如何修复“运算符不存在:text = uuid”?
【发布时间】:2019-12-14 03:32:44
【问题描述】:

我正在使用 postgres-simple 库插入eligible_class_passes 表。它本质上是一个表示多对多关系的连接表。

我正在使用postgres-simple 中的executeMany 函数进行多行插入。

updateEligibleClassPasses :: Connection -> Text -> Text -> [Text] -> IO Int64
updateEligibleClassPasses conn tenantId classTypeId classPassTypeIds =
  withTransaction conn $ do
    executeMany
      simpleConn
      [sql| 
      INSERT INTO eligible_class_passes (class_type_id, class_pass_type_id)
      SELECT upd.class_type_id::uuid, upd.class_pass_type_id::uuid
      FROM (VALUES (?, ?, ?)) as upd(class_type_id, class_pass_type_id, tenant_id)
      INNER JOIN class_types AS ct
      ON upd.class_type_id::uuid = ct.id
      INNER JOIN subscription_types AS st
      ON class_pass_type_id::uuid = st.id
      WHERE ct.tenant_id = upd.tenant_id::uuid AND st.tenant_id = upd.tenant_id::uuid
      |]
      params
 where
  addParams classPassTypeId = (classTypeId, classPassTypeId, tenantId)
  params = addParams <$> classPassTypeIds

当应用正确的参数执行此函数时,我得到以下运行时错误

SqlError {sqlState = "42883", sqlExecStatus = FatalError, sqlErrorMsg = "operator does not exist: text = uuid", sqlErrorDetail = "", sqlErrorHint = "No operator matches the given name and argument type(s). You might need to add explicit type casts."}

但是,当转换为没有参数替换 (?) 的 SQL 时,查询在 psql 中执行时可以正常工作。

INSERT INTO eligible_class_passes (class_type_id, class_pass_type_id)
SELECT upd.class_type_id::uuid, upd.class_pass_type_id::uuid
FROM (VALUES ('863cb5ea-7a68-41d5-ab9f-5344605de500', 'e9195660-fd48-4fa2-9847-65a0ad323bd5', '597e6d7a-092a-49be-a2ea-11e8d85d8f82')) as upd(class_type_id, class_pass_type_id, tenant_id)
INNER JOIN class_types AS ct
ON upd.class_type_id::uuid = ct.id
INNER JOIN subscription_types AS st
ON class_pass_type_id::uuid = st.id
WHERE ct.tenant_id = upd.tenant_id::uuid AND st.tenant_id = upd.tenant_id::uuid;        

我的架构如下

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE tenants (
  id UUID NOT NULL DEFAULT uuid_generate_v4() PRIMARY KEY, 
  name text NOT NULL UNIQUE, 
  email text NOT NULL UNIQUE, 
  created_at timestamp with time zone NOT NULL default now(), 
  updated_at timestamp with time zone NOT NULL default now()
);

CREATE TABLE class_types (
  id UUID NOT NULL DEFAULT uuid_generate_v4() PRIMARY KEY, 
  FOREIGN KEY (tenant_id) REFERENCES tenants (id), 
  created_at timestamp with time zone NOT NULL default now(), 
  updated_at timestamp with time zone NOT NULL default now()
);

CREATE TABLE class_pass_types (
  id UUID NOT NULL DEFAULT uuid_generate_v4() PRIMARY KEY, 
  name TEXT NOT NULL, 
  tenant_id UUID NOT NULL, 
  price Int NOT NULL, 
  created_at timestamp with time zone NOT NULL default now(), 
  updated_at timestamp with time zone NOT NULL default now(), 
  FOREIGN KEY (tenant_id) REFERENCES tenants (id)
);

-- Many to many join through table.
-- Expresses class pass type redeemability against class types.
CREATE TABLE eligible_class_passes (
  class_type_id UUID, 
  class_pass_type_id UUID, 
  created_at timestamp with time zone NOT NULL default now(), 
  updated_at timestamp with time zone NOT NULL default now(), 
  FOREIGN KEY (class_type_id) REFERENCES class_types (id) ON DELETE CASCADE, 
  FOREIGN KEY (class_pass_type_id) REFERENCES class_pass_types (id) ON DELETE CASCADE, 
  PRIMARY KEY (
    class_type_id, class_pass_type_id
  )
);

【问题讨论】:

    标签: sql postgresql haskell


    【解决方案1】:

    为了帮助调试您的问题,请使用formatQuery 函数,然后您可以看到postgresql-simple 正在向服务器发送什么样的最终查询。

    另外,我建议使用 uuid-types 包中的 UUID 类型,而不是使用 uuid 的 Text。使用Text 很可能会向您隐藏一些问题(希望您使用formatQuery 会看到这些问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2019-02-03
      • 2019-11-12
      相关资源
      最近更新 更多