在主键循环之后从PostgreSQL中选择记录?

时间:2019-01-10 17:38:52

标签: sql postgresql

我有一个PostgreSQL 9.5表,该表设置为在主键ID达到最大值时循环运行。出于参数考虑,让最大ID值可以为999,999。我将添加逗号以使数字更易于阅读。

我们运行了一个作业,该作业会删除早于45天的表中的数据。假设该表现在仅包含ID为999,998和999,999的记录。

主键ID循环回到1,并且已经写入了20条记录。我需要保持通用性,这样就不会对写入的数量做任何假设。在我的现实世界需求中,我不在乎写了多少书。

如何选择记录而不会获得ID为999,998和999,999的重复记录?

例如:

SELECT * FROM my_table WHERE ID >0;

Would return (in no particular order):

999,998
999,999
1
2
...
20

我的现实情况是,我需要将所有写入表的记录发布到消息代理。我维护一个单独的表,该表跟踪发布的最后一条记录的行ID和时间戳。确定要写入哪些新记录的伪查询/伪算法就是这样。 IF语句处理主键ID何时回到1,因为我需要读取ID循环之后写入的新记录:

SELECT * from my_table WHERE id > last_written_id
PUBLISH each record
if ID of last record published == MAX_TABLE_ID (e.g 999,999):
    ??? What to do here? I need to get the newest records where ID >= 1 but less than the oldest record I have

我意识到“代码”很粗糙,但是目前它只是一个想法,因此没有代码。

谢谢

3 个答案:

答案 0 :(得分:1)

嗯,您可以使用序列的当前值执行所需的操作:

select t.*
from my_table t
where t.id > @last_written_id or
      (currval(pg_get_serial_sequence('my_table', 'id')) < @last_written_id and
       t.id <= currval(pg_get_serial_sequence('my_table', 'id')) 
      );

这不是100%的解决方案。毕竟,可能已经添加了2,000,000条记录,所以这些数字将全部重复或删除记录。另外,如果在查询运行时发生插入操作-尤其是在多线程环境中。

答案 1 :(得分:0)

这是一种完全不同的方法:您可以完全填满表格,在表格中为其指定删除时间。因此,您只需设置此日期时间,而不是删除行。而不是插入一行,您只需更新最长时间前删除的那一行即可:

update my_table
set col1 = 123, col2 = 456, col3 = 'abc', deletion_datetime = null
where deletion_datetime = 
(
  select deletion_datetime
  from my_table
  where deletion_datetime is not null
  order by deletion_datetime
  limit 1
);

答案 2 :(得分:0)

如果您可以假定该范围的填充因子小于0.5,则效果很好:

import RPi.GPIO as GPIO
import serial
import time,sys


var=0b11110000
SERIAL_PORT = "/dev/ttyS0"
ser=serial.Serial(SERIAL_PORT,baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS)
time.sleep(1)
print("Sending")
ser.write(var)
ser.close()