Reputation: 1813
I am an SQL server developer working on a project in a PostgreSQL environment. I am having some PostgreSQL syntax issues. I am working off version 9.3.
In a given table, I am trying to set every 10 rows an increment of 1. Example:
CREATE TABLE x_list(
id varchar(100),
field1 varchar(20)
)
In the example, I have 100 rows. For the first 10 rows, the field1 value is '0001'. For the next 10 rows, the field1 value is '0002'. For the next 10 rows, the field1 value is '0003' and so on.
This is what I have so far:
DECLARE
lp_cnt INTEGER := 1;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM x_list WHERE field1 IS NULL) THEN
UPDATE x_list
SET field1 = RIGHT('0000' + lp_cnt::VARCHAR, 4)
WHERE id IN (SELECT id FROM x_list WHERE field1 IS NULL LIMIT 10)
lp_cnt := lp_cnt + 1
END IF;
END $$;
I am getting the following error:
ERROR: syntax error at or near "INTEGER"
LINE 2: lp_cnt INTEGER := 1;
^
********** Error **********
ERROR: syntax error at or near "INTEGER"
SQL state: 42601
Character: 18
I am not sure how to solve the error. I tried replacing INTEGER
with INT
I am also open to a better way to accomplish my goal.
Upvotes: 1
Views: 74
Reputation: 26113
You can handle this using a plain, non-procedural-SQL update
with a CTE, a row_number()
window function and /
integer division.
demo at db-fiddle
with cte as (
select ctid
, 1+(row_number()over(order by id::int)-1)/10 as rn
from x_list)
update x_list
set field1=lpad(rn::text,4,'0')
from cte
where x_list.ctid=cte.ctid;
This uses a hidden system column ctid
instead of id
because according to your table definition, id
isn't necessarily unique. Also, I'm using lpad()
for left-padding the zeroes. The added and subtracted 1's are there to start from 1, not 0, and to increment after 10's, not 9's.
Although a bit more slowly, your idea could still work if you fix it:
loop
for as long as there are things left to update.declare
belongs inside the do
block.exists()
subquery - it only checks if any rows are returned but all their columns are discarded.DO $d$
DECLARE lp_cnt INTEGER := 1;
BEGIN
WHILE EXISTS (SELECT FROM x_list WHERE field1 IS NULL) LOOP
UPDATE x_list
SET field1 = RIGHT('0000' ||lp_cnt::text, 4)
WHERE id IN (SELECT id FROM x_list
WHERE field1 IS NULL
ORDER BY id::int LIMIT 10);
lp_cnt := lp_cnt + 1;
END loop;
END $d$;
select*from x_list order by id::int limit 11;
id | field1 |
---|---|
1 | 0001 |
2 | 0001 |
3 | 0001 |
4 | 0001 |
5 | 0001 |
6 | 0001 |
7 | 0001 |
8 | 0001 |
9 | 0001 |
10 | 0001 |
11 | 0002 |
Consider an upgrade: PostgreSQL 9.3 support ended in 2018.
Upvotes: 2