| 123456789101112131415161718192021222324252627282930313233343536373839 |
- -- 乐收赢去企业化(租户账号级)2026-09-22
- -- 手工执行: psycopg2 连接 payment_platform_java 库
- --
- -- 背景: 乐收赢与原有企业逻辑完全不相干,商户映射应按**租户账号**寻址。
- -- 本脚本让 pay_lsy_merchant 支持「租户级商户」—— enterprise_id 为空的那一行。
- -- 不新增列、不新增表;订单表 pay_lsy_order.enterprise_id 建表时已可空,本脚本不碰它。
- --
- -- ⚠ 第一条**不可逆**: NOT NULL 加不回来,除非先把所有 enterprise_id IS NULL 的行清掉
- -- 或补上企业 ID。执行前请确认可以接受。
- --
- -- ⚠ **先执行本脚本,再部署代码**(顺序不能反)。配套的代码提交删掉了 save 里
- -- 「企业 ID 不能为空」的 400 校验,而列还是 NOT NULL 的话,留空保存会从 400
- -- 变成 500(NOT NULL 违约落进 GlobalExceptionHandler 兜底)。
- -- 本脚本执行前,现有行为一切照旧(老调用方都带 enterprise_id)。
- -- 1. 允许租户级商户
- ALTER TABLE pay_lsy_merchant ALTER COLUMN enterprise_id DROP NOT NULL;
- -- 2. 租户级商户的唯一性
- -- 现有唯一索引 uk_lsy_merchant_tenant_ent 建在 (tenant_id, enterprise_id) 上,
- -- 而 PostgreSQL 唯一索引里 **NULL 互不相等** ⇒ 缺了下面这条局部索引,
- -- 同一个租户可以插入任意多行租户级商户,数据库一声不吭,
- -- 之后 requireByTenant 的 LIMIT 1 会随机返回其中一行。
- --
- -- 存量数据核对(2026-09-22 只读实测,非推断):全表 1 行
- -- id=1, tenant_id=2, enterprise_id='2088780645490698', mch_no='Y52211090004'
- -- 该行 enterprise_id **非空**,落在局部索引的谓词之外 ⇒ 不冲突,无需清理。
- -- 将来若真出现同租户多行租户级商户(只可能来自索引建成之前的窗口),先清理再建索引:
- -- DELETE FROM pay_lsy_merchant a USING pay_lsy_merchant b
- -- WHERE a.id < b.id AND a.tenant_id = b.tenant_id
- -- AND a.enterprise_id IS NULL AND b.enterprise_id IS NULL;
- CREATE UNIQUE INDEX IF NOT EXISTS uk_lsy_merchant_tenant_level
- ON pay_lsy_merchant (tenant_id)
- WHERE enterprise_id IS NULL;
- -- 3. 只读核对(执行后可手工跑一遍确认)
- -- SELECT is_nullable FROM information_schema.columns
- -- WHERE table_name='pay_lsy_merchant' AND column_name='enterprise_id'; -- 期望 YES
- -- SELECT indexname FROM pg_indexes WHERE tablename='pay_lsy_merchant'; -- 期望含上述两条
|