暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL SQL写出变态味,可以!(附带两个哑谜)

AustinDatabases 2024-12-31
81

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共2650人左右 1 + 2 + 3 + 4 +5 + 6 + 7 + 8 )(1 2 3 4 5 6群均已爆满,新人进7群380+,8群,准备9群)

今天不说没礼貌的故事了,今天换一个话题,等“没礼貌”的在来找,在继续写。 今天说SQL的问题,这个话题会一分为二

PostgreSQL 什么都能存,什么都能塞 --- 你能成熟一点吗?

PostgreSQL 迁移用户很简单 ---  我看你的好戏

PostgreSQL  用户胡作非为只能受着 --- 警告他

PostgreSQL  加索引系统OOM 怨我了--- 不怨你怨谁

PostgreSQL  “我怎么就连个数据库都不会建?”   --- 你还真不会!

1  丧心病狂的SQL 的分析

2  为什么会产生这个错误



开始说SQL,说一个丧心病狂的SQL,(认为本文是说SQL撰写的问题,那就大错特错了,咱们是另一个角度)先看这个SQL。

SELECT
   stage.id,
   stage.pipeline_id,
   stage.environment_id,
   stage.name,
   (
    SELECT EXISTS (
     SELECT 1 FROM task
     LEFT JOIN LATERAL (
      SELECT COALESCE(
       (SELECT
        task_run.status
       FROM task_run
       WHERE task_run.task_id = task.id
       ORDER BY task_run.id DESC
       LIMIT 1
       ), 'NOT_STARTED'
      ) AS status
     ) AS latest_task_run ON TRUE
     WHERE task.pipeline_id = stage.pipeline_id
     AND task.stage_id <= stage.id
     AND NOT (
      COALESCE((task.payload->>'skipped')::BOOLEAN, FALSE) IS TRUE
      OR latest_task_run.status = 'DONE'
     )
    )
   ) AS active
  FROM stage
  WHERE %s ORDER BY id ASC

在看完这个SQL后,我不知道各位看官怎么想,我的想法是,够狠,够虐,够聪明。从多年的SQL观察和优化的角度,这个SQL的撰写者并不一般这是一个知名的软件中我们运行出现问题的SQL,执行中报错,报can not add sublink to placeholder_list。

为什么说这个SQL是丧心病狂的 

1  这个SQL撰写成这样是有原因的,明显是为了软件不被破译而做的手段。

 2  撰写者非常的狡猾,利用了一个SQL完成了一个简单的业务逻辑的判断程序。

结论:现在SQL都能这么玩了,SQL现在有防盗,防贼,防闺蜜的能力了。

那么我们现在来破译一下,这个SQL的原理和他到底要干什么。

SELECT 1 FROM task
     LEFT JOIN LATERAL (
      SELECT COALESCE(
       (SELECT
        task_run.status
       FROM task_run
       WHERE task_run.task_id = task.id
       ORDER BY task_run.id DESC
       LIMIT 1
       ), 'NOT_STARTED'
      ) AS status
     ) AS latest_task_run ON TRUE
     WHERE task.pipeline_id = 106
     AND task.stage_id <= 106
     AND NOT (
      COALESCE((task.payload->>'skipped')::BOOLEAN, FALSE) IS TRUE
      OR latest_task_run.status = 'DONE'
     )

这段语句可能一般的人,一时半刻解不开这里面到底是什么意思,这里我先做一个解释。这段代码虽然是SQL,但不要把他当SQL看,一段程序,一段具有多个判断能力的程序。

我们逐级的将这段SQL拆开。

核心部分 1

先说这段,这段的意思是,从task_run 表中取值与另一个表task,将两者的id进行比对,然后得到task_run的status,然后取其中的最后一条数据,如果这条数据有,则通过coalesce将他的状态展示,如果根本就没有数据,那么就直接显示 not_started 作为状态。

SELECT COALESCE(
 (SELECT
 task_run.status
 FROM task_run
 WHERE task_run.task_id = task.id
 ORDER BY task_run.id DESC
 LIMIT 1
 ), 'NOT_STARTED'
 ) AS status

扩大部分 2

SELECT 1 FROM task
     LEFT JOIN LATERAL (
      SELECT COALESCE(
       (SELECT
        task_run.status
       FROM task_run
       WHERE task_run.task_id = task.id
       ORDER BY task_run.id DESC
       LIMIT 1
       ), 'NOT_STARTED'
      ) AS status
     ) AS latest_task_run ON TRUE

这里我看看到了主表 task,而 left join lateral 的意思为for each ,意思是task表中的每一行,与下面的子查询返回的值进行循环,ON TRUE 是建立无条件的连接。最终结果返回1。

继续扩大 3

这段是对执行的结果进行判断,如果表中的数据任务符合where条件的假设,

task.pipeline_id = stage.pipeline_id
task.stage_id <= stage.id
NOT (COALESCE((task.payload->>'skipped')::BOOLEAN, FALSE)
IS TRUE
OR latest_task_run.status = 'DONE'

那么select exists 就是 true,如果没有符合的记录出现,那么打印的就是 false。

SELECT EXISTS (
     SELECT 1 FROM task
     LEFT JOIN LATERAL (
      SELECT COALESCE(
       (SELECT
        task_run.status
       FROM task_run
       WHERE task_run.task_id = task.id
       ORDER BY task_run.id DESC
       LIMIT 1
       ), 'NOT_STARTED'
      ) AS status
     ) AS latest_task_run ON TRUE
     WHERE task.pipeline_id = stage.pipeline_id
     AND task.stage_id <= stage.id
     AND NOT (
      COALESCE((task.payload->>'skipped')::BOOLEAN, FALSE) IS TRUE
      OR latest_task_run.status = 'DONE'
     )
    )

所以这个语句最后呈现的影子应该是这样,与此同时SQL作者在这里还有一个where 带的变量条件,让这个SQL变换莫测。

            SELECT
   stage.id,
   stage.pipeline_id,
   stage.environment_id,
   stage.name,
            (True/False)
            FROM stage
      WHERE %s ORDER BY id ASC

通过这个SQL是可以完全得出,这个软件的设计者很鸡贼,尽力保护自己的程序不被破译,这应该是这个软件流程方面核心的一部分。

Bravo, Bravo, Bravo !!!!

(因为程序员对SQL的理解并不清楚,所以这个程序员通过SQL来对自己的程序进行加密,程序员多会一门语言是多么的重要!! 明明可以写成程序,但不,他要用SQL来写他的程序)

说完这个SQL的巧妙,我们进入下一个话题,PostgreSQL报错了,且还是PG14.12 不报错,PG14.13报错(也没有这么简单,后面再说,实际上也不是纯种的开源PG)

错误的产生可能来自, “无法将子链接添加到占位符列表” 错误发生是因为在用 WHERE 子句中子链接(LATERAL连接内部的子查询),特别是在COALESCE函数内部。PostgreSQL 在这种情况下不允许子链接。

对于这样的问题,我们可以对这个SQL进行改写来改变其中的可能产生报错的问题,那么以上语句可以用修改语句的方式来解决遇到的问题,比如将子查询改为CTE

WITH latest_status AS (
    SELECT
        task.id AS task_id,
        COALESCE(
            (SELECT task_run.status
             FROM task_run
             WHERE task_run.task_id = task.id
             ORDER BY task_run.id DESC
             LIMIT 1), 'NOT_STARTED'
        ) AS status
    FROM task
)
SELECT task.*, latest_status.status
FROM task
LEFT JOIN latest_status ON task.id = latest_status.task_id
WHERE task.pipeline_id = $1
  AND task.stage_id <= $2
  AND NOT (
      COALESCE((task.payload->>'skipped')::BOOLEAN, FALSE) IS TRUE
      OR latest_status.status = 'DONE'
  );

这样可以解决问题,现实中,我仅仅动用了一个位置就解决了问题。将语句改为join 而不是left join,语句就顺利的运行了。这里提醒在修改这个部分的时候,要明确你修改后是否会影响业务的逻辑,这里简单的分析应该是不影响业务逻辑。

虽然修改了语句解决了问题,但还是觉得不妥,所以询问了这个数据库的出品方,然后在鬼使神差的情况下,这个问题就好了,修改了参数 lazy_process_sublink参数。

那么这篇文章出了两个谜语,这个SQL属于当今那个火热的软件,运行这个SQL的数据库又是那个?猜的出来吗?

总结:这样撰写SQL,只能是开发人员写出来的高阶预防程序软件被破译的门槛,正常的人员一般不会这样撰写SQL,不过今天也让我涨了见识。SQL 还可以这样写。


PostgreSQL 相关文章
PostgreSQL 什么都能存,什么都能塞 --- 你能成熟一点吗?
PostgreSQL 迁移用户很简单 ---  我看你的好戏

PostgreSQL 用户胡作非为只能受着 --- 警告他

全世界都在“搞” PostgreSQL ,从Oracle 得到一个“馊主意”开始PostgreSQL 加索引系统OOM 怨我了--- 不怨你怨谁

PostgreSQL “我怎么就连个数据库都不会建?” --- 你还真不会!

病毒攻击PostgreSQL暴力破解系统,防范加固系统方案(内附分析日志脚本)
PostgreSQL 远程管理越来越简单,6个自动化脚本开胃菜

PostgreSQL 稳定性平台 PG中文社区大会--杭州来去匆匆

PostgreSQL 如何通过工具来分析PG 内存泄露

PostgreSQL  分组查询可以不进行全表扫描吗?速度提高上千倍?

POSTGRESQL --Austindatabaes 历年文章整理

PostgreSQL  查询语句开发写不好是必然,不是PG的锅

PostgreSQL  字符集乌龙导致数据查询排序的问题,与 MySQL 稳定 "PG不稳定"
PostgreSQL  Patroni 3.0 新功能规划 2023年 纽约PG 大会 (音译)
PostgreSQL   玩PG我们是认真的,vacuum 稳定性平台我们有了
PostgreSQL DBA硬扛 垃圾 “开发”,“架构师”,滥用PG 你们滚出 !(附送定期清理连接脚本)

DBA 失职导致 PostgreSQL 日志疯涨


PolarDB 相关文章
PolarDB 版本差异分析--外人不知道的秘密(谁是绵羊,谁是怪兽)

PolarDB 答题拿-- 飞刀总的书、同款卫衣、T恤,来自杭州的Package(活动结束了)

PolarDB for MySQL 三大核心之一POLARFS 今天扒开它--- 嘛是火星人

PolarDB-MySQL 并行技巧与内幕--(怎么薅羊毛)

PolarDB 并行黑科技--从百套MySQL撤下说起 (感谢8018个粉丝的支持)

PolarDB 杀疯了,Everywhere Everytime Everydatabase on Serverless

POLARDB  从一个使用者的角度来说说,POALRDB 怎么打败 MYSQL RDS

PolarDB 最近遇到加字段加不上的问题 与 使用PolarDB 三年感受与恳谈

PolarDB 从节点Down机后,引起的主从节点强一致的争论

PolarDB serverless 真敢搞,你出圈了你知道吗!!!!

PolarDB VS PostgreSQL  "云上"性能与成本评测 -- PolarDB 比PostgreSQL 好?

临时工访谈:PolarDB  Serverless  发现“大”问题了  之 灭妖记 续集

临时工访谈:庙小妖风大-PolarDB 组团镇妖 之 他们是第一

PolarDB for PostgreSQL  有意思吗?有意思呀
PolarDB  Serverless POC测试中有没有坑与发现的疑问
临时工说:从人性的角度来分析为什么公司内MySQL 成为少数派,PolarDB 占领高处
POLARDB  到底打倒了谁  PPT 分享 (文字版)

POLARDB  -- Ausitndatabases 历年的文章集合

PolarDB for PostgreSQL  有意思吗?有意思呀

PolarDB  搞那么多复杂磁盘计费的东西,抽筋了吗?


临时工访谈系列
Oracle 文化走后,你我只值9.9元
知人者智,自知者明,琼瑶一路走好
本地存储还有活路吗? 从上周一个供应商问我的问题开始
一年又一年,成了老梆子,别回头,往前看!
临时工说: 实际实例揭穿AI, 上云就不用DBA的谎言
临时工说:DBA 7*24H 给2万的工作,到底去不去?
国内最大IT服务公司-招聘DBA “招聘广告”的变化--分析与探讨
临时工说:  网友问35岁就淘汰,我刚入行DBA 怎么办?

OceanBase 相关文章
OceanBase4.0 跟我学--分布式到底可靠不可靠,到底丢不丢数-- 核心实现
OceanBase  送祝福活动,礼物和幸运带给您

跟我学OceanBase4.0 --阅读白皮书 (OB分布式优化哪里了提高了速度)

跟我学OceanBase4.0 --阅读白皮书 (4.0优化的核心点是什么)

跟我学OceanBase4.0 --阅读白皮书 (0.5-4.0的架构与之前架构特点)

跟我学OceanBase4.0 --阅读白皮书 (旧的概念害死人呀,更新知识和理念)

聚焦SaaS类企业数据库选型(技术、成本、合规、地缘政治)

OceanBase 学习记录-- 建立MySQL租户,像用MySQL一样使用OB
OceanBase  学习记录 -- 安装简易环境
OceanBase  学习记录 --  开始入门
数据库最近第一比较多,OceanBase 定语加多了?
临时工访谈:OceanBase上海开大会,我们四个开小会 OB 国产数据库破局者
临时工说:OceanBase 到访,果然数据库的世界很卷,没边
数据库信息速递  阿里巴巴的分布式数据库OceanBase旨在进军中国以外的市场 (翻译)

SQL SERVER 系列

SQL SERVER维保AI化,从一段小故事开始
SQL SERVER 如何实现UNDO REDO 和PostgreSQL 有近亲关系吗
SQL SERVER 危险中,标题不让发,进入看详情(译)
SQL SERVER 我没有消失,SQL SERVER下一个版本是2025 (功能领先大多数数据库)
SQL SERVER 2022 针对缓存扫描和Query Store 的进步,可以考虑进行版本升级


MongoDB 相关文章


MongoDB 合作考试报销活动 贴附属,MongoDB基础知识速通

MongoDB 年底活动,免费考试名额 7个公众号获得

MongoDB 使用网上妙招,直接DOWN机---清理表碎片导致的灾祸 (送书活动结束)

数据库 《三体》“二向箔”  思维限制 !8个公众号联合抽奖送书 建立数据库设计新思维

MongoDB  是外星人,水瓶座,怎么和不按套路出牌的他沟通?

17000多张MongoDB表的锅 自动分析删除表数据难题--从头到尾的处理过程(文尾有MongoDB开发规范)
MongoDB 插入更新数据慢,开发问哪的问题?附带解决方案和脚本
MongoDB 不是软柿子,想替换就替换
MongoDB  挑战传统数据库聚合查询,干不死他们的MongoDB 2023纽约 MongoDB 大会 -- 我们怎么做的新一代引擎 SBE Mongodb 7.0双擎力量(译)
MongoDB 2023年度纽约 MongoDB 年度大会话题 -- MongoDB 数据模式与建模
MongoDB  双机热备那篇文章是  “毒”
MongoDB   会丢数据吗?在次补刀MongoDB  双机热备
MONGODB  ---- Austindatabases  历年文章合集


MySQL相关文章


MySQL 怎么让自己更高级---从内存表说到了开发方式
MySQL timeout 参数可以让事务不完全回滚
"DBA 是个der" 吵出MySQL主键问题多种解决方案

MySQL 让你还用5.7 出事了吧,用着用着5.7崩了

MySQL 的SQL引擎很差吗?由一个同学提出问题引出的实验
用MySql不是MySQL, 不用MySQL都是MySQL 横批 哼哼哈哈啊啊
MYSQL  --Austindatabases 历年文章合集

阿里云系列

阿里云数据库产品权限设计缺陷 ,六个场景诠释问题,你可以做的更好?

阿里云数据库--市场营销聊胜于无--3年的使用感受与反馈系列

阿里云数据库产品 对内对外一样的卷 --3年阿里云数据库的使用感受与反馈系列

阿里云数据库使用感受--客户服务问题深入剖析与什么是廉价客户 --3年的使用感受与反馈系列

阿里云数据库使用感受--操作界面有点眼花缭乱 --3年的使用感受与反馈系列



文章转载自AustinDatabases,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论