PostgreSQL函数:查询包含时间分区字段的表,并更新dt分区为最新分区

该博客介绍了如何设计并实现一个PL/pgSQL函数,用于在无法连接客户库时,自动更新ods环境中包含dt字段的表的dt值为当前日期。通过查询数据库元数据获取ods层包含dt字段的表名,然后遍历更新每个表,确保即使在特定条件下,数据处理脚本也能正常运行并获取最新数据。

一、需求

1、背景

提出新需求后,需要在www环境下进行验收。故需要将www环境脚本每天正常调度

但由于客户库无法连接,ods数据无法每日取,且连不上客户库任务直接报错,不会跑ods之后的任务

故需要让调度正常运行,且能在事实表中看到最新的分区,有的脚本从ods中取数据时取的是where dt=(select max(dt) from ods.xxx)

但有的脚本取的是where dt = to_char(now(),'yyyymmdd'),故运行时,事实表获取不到当日数据

故需要本函数用于更新dt字段

2、需求

找包含dt字段的表,并将这些表的dt值更新为最近的dt

二、函数内容

1、函数内容

CREATE OR REPLACE FUNCTION "ods"."upd_dt_newly_to_now"()
  RETURNS "pg_catalog"."void" AS $BODY$
  DECLARE arrat_t varchar[];
	DECLARE tb_each VARCHAR;
  BEGIN
        select array(SELECT DISTINCT
        C.relname
        FROM
        pg_class AS C,
        pg_attribute AS A,
        pg_tables AS B
        WHERE A.attrelid = C.oid
        and C.relname = B.tablename
        AND A.attnum > 0
        AND B.schemaname = 'ods'
        AND B.tablename NOT SIMILAR TO
<think>我们需要从给定的时间字符串中解析出时间,然后计算当前时间减去14天,最后比较dt字段是否小于这个时间点。 注意:给定的时间字符串是"2025-07-14 13:40:46",但当前时间应该是动态的(即代码运行时的当前时间),而这里要求的是小于当前时间减去14天。 然而,问题中给出的时间字符串是一个未来的时间(2025年),所以实际上我们不需要使用这个字符串作为当前时间,而是使用系统当前时间(now)减去14天。 步骤: 1. 获取当前时间(now) 2. 计算当前时间减去14天(now - timedelta(days=14)) 3. 将需要比较的dt字段(字符串形式)转换为datetime对象,然后与计算出的时间进行比较。 但是,问题描述中没有明确说明数据存储的形式。我们假设dt字段是以字符串形式存储的,格式为"YYYY-MM-DD HH:MM:SS"。 在SQL中,我们可以使用日期函数来实现。但是问题没有指定数据库类型,我们以常用的MySQL和PostgreSQL为例。 在MySQL中: 我们可以使用DATE_SUB函数来减去14天,然后与字段比较。注意,如果dt是字符串,需要转换为日期类型。 例如:WHERE STR_TO_DATE(dt, '%Y-%m-%d %H:%i:%s') < DATE_SUB(NOW(), INTERVAL 14 DAY) 但是,如果dt字段已经是日期类型(如DATETIME),则可以直接比较: WHERE dt < DATE_SUB(NOW(), INTERVAL 14 DAY) 在PostgreSQL中: 使用类似的方法:WHERE dt::timestamp < CURRENT_TIMESTAMP - INTERVAL '14 days' 然而,问题中给出的时间字符串是"2025-07-14 13:40:46",这显然是一个未来的时间。所以,如果当前时间(假设为2024年)减去14天,那么2025年的数据不会满足条件(因为2025年大于当前时间减去14天)。但根据问题,我们是要取出小于(当前时间-14天)的数据,所以2025年的数据不会被取出。 但是,问题要求的是“取出小于当前时间减去14天的数据”,所以我们需要的是过去的时间(早于14天前的数据)。 注意:这里有一个潜在的歧义,就是“当前时间”是指什么?在代码执行时,当前时间是动态的,而问题中给出的时间字符串可能只是示例,实际比较时应该用系统当前时间。 因此,我们假设需求是:取dt字段的值小于(当前系统时间减去14天)的所有记录。 如果是在编程语言中(如Python),我们可以这样处理: from datetime import datetime, timedelta # 当前时间 current_time = datetime.now() # 14天前的时间 fourteen_days_ago = current_time - timedelta(days=14) # 然后,将数据库中的dt字符串转换为datetime对象,与fourteen_days_ago比较 # 假设从数据库取出的每条记录有一个dt_str,格式为"YYYY-MM-DD HH:MM:SS" # 我们可以这样转换:record_time = datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S") # 然后判断 record_time < fourteen_days_ago 但是,通常我们不会在应用层做这样的过滤(特别是大数据量时),而是在数据库层用SQL过滤。 所以,重点在于如何写SQL。 由于问题没有指定数据库,我们给出两种常见数据库的写法: MySQL: SELECT * FROM table_name WHERE dt < DATE_SUB(NOW(), INTERVAL 14 DAY); 注意:这里假设dt字段是DATETIME类型。如果是字符串类型,则需要先转换: SELECT * FROM table_name WHERE STR_TO_DATE(dt, '%Y-%m-%d %H:%i:%s') < DATE_SUB(NOW(), INTERVAL 14 DAY); PostgreSQL: SELECT * FROM table_name WHERE dt::TIMESTAMP < CURRENT_TIMESTAMP - INTERVAL '14 days'; 或者如果字段是字符串: SELECT * FROM table_name WHERE TO_TIMESTAMP(dt, 'YYYY-MM-DD HH24:MI:SS') < CURRENT_TIMESTAMP - INTERVAL '14 days'; 另外,考虑到性能,如果dt字段是字符串类型,建议在数据库设计时更改为日期时间类型,建立索引。 但是,问题中给出的时间字符串是"2025-07-14 13:40:46",这是一个未来的时间,所以它不会满足条件(因为当前时间减去14天是过去的时间,未来的时间不会小于过去的时间)。 所以,实际上这个条件会筛选出所有在14天之前的数据(即旧数据)。 总结:根据需求,我们需要的是dt字段的值早于(当前时间-14天)的数据。 最后,根据规则,我们需要在回答后提出3-5个相关问题。 注意:问题中的时间字符串只是一个示例,实际比较时用系统当前时间。 因此,回答如下:</think>### 问题分析及解决方案 您需要筛选出 `dt` 字段值小于 **当前时间减去14天** 的数据。以下是具体实现方法(假设 `dt` 字段存储格式为 `2025-07-14 13:40:46`): #### 1. **SQL 实现(通用写法)** ```sql SELECT * FROM 名 WHERE dt < CURRENT_TIMESTAMP - INTERVAL '14 DAY' -- 标准写法(推荐) -- 或兼容写法(某些数据库需用函数): -- dt < DATEADD(DAY, -14, GETDATE()) -- SQL Server -- dt < NOW() - INTERVAL 14 DAY -- MySQL -- dt < CURRENT_DATE - 14 -- PostgreSQL(日期模式) ``` #### 2. **关键说明** - **时间计算逻辑**: `CURRENT_TIMESTAMP - INTERVAL '14 DAY'` 会动态计算当前时刻的 **14天前** 的时间点 *示例*:若当前时间是 `2024-06-04 10:00:00`,则筛选条件为 `dt < 2024-05-21 10:00:00` - **字段要求**: `dt` 字段必须是 **日期时间类型**(如 `DATETIME`, `TIMESTAMP`)。若为字符串类型需先转换: ```sql WHERE STR_TO_DATE(dt, '%Y-%m-%d %H:%i:%s') < ... -- MySQL WHERE TO_TIMESTAMP(dt, 'YYYY-MM-DD HH24:MI:SS') < ... -- PostgreSQL ``` - **时区注意事项**: 确保数据库服务器的时区与应用一致(避免时差导致筛选偏差),可通过 `SET time_zone='+08:00'` 调整 #### 3. **性能优化建议** - 为 `dt` 字段创建索引:`CREATE INDEX idx_dt ON 名(dt)` - 避免在 `WHERE` 子句中对字段进行函数转换(防止索引失效) - 大数据建议分批操作:`LIMIT` + 循环 或使用分区 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值