Where to find Netezza Sequence data? - sequence

Information about sequences can be found in the _vt_sequence view which can be joined with _v_sequence on _v_sequence.objid = _vt_sequence.seq_id.
sequence fetch query :
select vs.* , vts.*
from _v_sequence vs join _vt_sequence vts on vs.objid = vts.seq_id;
Following values generated out of queries :
OBJID
SEQNAME
OWNER
CREATEDATE
OBJTYPE
OBJCLASS
OBJDELIM
DATABASE
OBJDB
SCHEMA
SCHEMAID
SEQ_ID
DB_ID
DATA_TYPE
MIN_VALUE
MAX_VALUE
CYCLE
INCREMENT
CACHE_SIZE
NEXT_CACHE_VAL
FLAGS
Sample CREATE SEQUNCE:
CREATE SEQUENCE TEMP_PPC_SEQ AS BIGINT
START WITH 1
INCREMENT BY 2
NO MINVALUE
MAXVALUE 2147483647
NO CYCLE;
There is no value for START of sequence.
Help to fetch START value of each sequence.

You can find start value in sequence table. Unfortunately netezza don't update last value in this table. Your answer is
SELECT s.LAST_VALUE
FROM sequence1 s;

You can find the "START WITH" value used by the DDL at creation time by selecting from the sequence object itself, as if it were a table, and referencing the LAST_VALUE column.
Don't be confused by the column name. LAST_VALUE does not report the last value dispensed by the sequence. The below example demonstrates this.
TESTDB.ADMIN(ADMIN)=> create sequence test_seq_1 as bigint start with 12345;
CREATE SEQUENCE
TESTDB.ADMIN(ADMIN)=> create temp table seq_out as select next value for test_seq_1 from _v_vector_idx a cross join _v_vector_idx b;
INSERT 0 1048576
TESTDB.ADMIN(ADMIN)=> select * from test_seq_1;
SEQUENCE_NAME | LAST_VALUE | INCREMENT_BY | MAX_VALUE | MIN_VALUE | CACHE_VALUE | LOG_CNT | IS_CYCLED | IS_CALLED | DATATYPE
---------------+------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------+----------
TEST_SEQ_1 | 12345 | 1 | 9223372036854775807 | 1 | 100000 | 1 | f | f | 20
(1 row)
TESTDB.ADMIN(ADMIN)=> select next value for test_seq_1;
NEXTVAL
---------
1060921
(1 row)

Related

How to use a new serial ID for each new batch of inserted rows?

Is it possible to use a sequence for a batch of rows, versus getting a new ID on each insert? I'm keeping track of a set of details, and I want the sequence to apply for the set, not each individual row. So my data should look like so:
id batch_id name dept
1 99 John Engineering
2 99 Amy Humanities
3 99 Bill Science
4 99 Jack English
It's the batch_id that I want Postgres to issue as a sequence. Is this possible?
Define batch_id as batch_id bigint not null default currval('seqname') and call nextval('seqname') manually before inserting batch of rows.
Or, for the full automation:
1) Create sequence for the batch id:
create sequence mytable_batch_id;
2) Create your table, declare batch id field as below:
create table mytable (
id bigserial not null primary key,
batch_id bigint not null default currval('mytable_batch_id'),
name text not null);
3) Create statement level trigger to increment the batch id sequence:
create function tgf_mytable_batch_id() returns trigger language plpgsql
as $$
begin
perform nextval('mytable_batch_id');
return null;
end $$;
create trigger tg_mytablebatch_id
before insert on mytable
for each statement execute procedure tgf_mytable_batch_id();
Now each single statement when you inserting data into the table will be interpreted as next single batch.
Example:
postgres=# insert into mytable (name) values('John'), ('Amy'), ('Bill');
INSERT 0 3
postgres=# insert into mytable (name) values('Jack');
INSERT 0 1
postgres=# insert into mytable (name) values('Jimmmy'), ('Abigail');
INSERT 0 2
postgres=# table mytable;
id | batch_id | name
----+----------+-------------
1 | 1 | John
2 | 1 | Amy
3 | 1 | Bill
4 | 2 | Jack
5 | 3 | Jimmy
6 | 3 | Abigail
(6 rows)

postgresql sequence getting max_value

How to get max_value and min_value Postgres sequence?
I created the sequence using this statement
create sequence seqtest increment 1 minvalue 0 maxvalue 20;
I tried this query select max_value from seqtest gives error
ERROR: column "max_value" does not exist
LINE 1: select max_value from seqtest;
HINT: Perhaps you meant to reference the column "seqtest.last_value".
Output of select * from seqtest
test=# select * from seqtest;
-[ RECORD 1 ]-
last_value | 0
log_cnt | 0
is_called | f
t=# create sequence seqtest increment 1 minvalue 0 maxvalue 20;
CREATE SEQUENCE
t=# select * from pg_sequence where seqrelid = 'seqtest'::regclass;
seqrelid | seqtypid | seqstart | seqincrement | seqmax | seqmin | seqcache | seqcycle
----------+----------+----------+--------------+--------+--------+----------+----------
16479 | 20 | 0 | 1 | 20 | 0 | 1 | f
(1 row)
Postgres 10 introduced new catalog: https://www.postgresql.org/docs/10/static/catalog-pg-sequence.html
also:
https://www.postgresql.org/docs/current/static/release-10.html
. Move sequences' metadata fields into a new pg_sequence system catalog
(Peter Eisentraut)
A sequence relation now stores only the fields that can be modified by
nextval(), that is last_value, log_cnt, and is_called. Other sequence
properties, such as the starting value and increment, are kept in a
corresponding row of the pg_sequence catalog.
Alternatively, it can be achieved using psql prompt using the command
\d
postgres=# \d seqtest
Sequence "public.seqtest"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
--------+-------+---------+---------+-----------+---------+-------
bigint | 0 | 0 | 20 | 1 | no | 1
select min_value, max_value from pg_sequences where sequencename = 'seqtest';
https://www.postgresql.org/docs/10/view-pg-sequences.html
But this query shows seqmax=9223372036854775807 (2^63-1) for any kind of sequence somehow.

Check if Integer is between a range of column values

Consider the following table schema:
----------------------------------
| ID | MinValue | MaxValue |
----------------------------------
| 1 | 0 | 10 |
| 2 | 11 | 20 |
| 3 | 21 | 30 |
I want to be able to pass an integer, and have it return the appropriate ID where that value matches the range between Min and Max Value.
EG:
Input = 17
Output = 2
Input = 4
Output = 1
Input = 26
Output = 3
I thought I could do something like:
SELECT ID FROM MyTable WHERE MinValue >= #input AND MaxValue <= #input
But it doesn't work, nothing is returned.
I'm sure the solution is blatantly simple, but i'm stumped.
What's the best way to achieve this in SQL Server?
try this
SELECT ID FROM MyTable WHERE #input BETWEEN MinValue AND MaxValue
DESCRIPTION of BEETWEEN
The SQL BETWEEN Condition is used to retrieve values within a range in a SELECT, INSERT, UPDATE, or DELETE statement.
SYNTAX
The syntax for the SQL BETWEEN Condition is:
expression BETWEEN value1 AND value2;
Parameters or Arguments
expression is a column or calculation.
value1 and value2 create an inclusive range that expression is compared to.
NOTE
The SQL BETWEEN Condition will return the records where expression is within the range of value1 and value2 (inclusive).
ref: http://www.techonthenet.com/sql/between.php
or you can also use like
MinValue <= #input AND MaxValue >= #input
Try this,
SELECT ID FROM MyTable WHERE #input BETWEEN MinValue AND MaxValue.
Or flip the equality signs in your statement.
SELECT ID FROM MyTable WHERE MinValue <= #input AND MaxValue >= #input
Use BETWEEN
SELECT ID
FROM MyTable
WHERE #input BETWEEN MinValue AND MaxValue

Use WITH to loop over a set of data in SQL

Given the following fields below, I'm trying to loop to the first iteration of the total set of iterations.
+-------------------+----------------------+------------------------+
| id | nextiterationId | iterationCount |
+-------------------+----------------------+------------------------+
| 110001 | 110002 | 0 |
| 110002 | 110003 | 1 |
| 110003 | 110004 | 2 |
| 110004 | 1 | 3 |
So if I call a SP/function using one of the values of the id field, I need it return the prior iterations of the id given until iterationCount = 0.
So If I use id of 110003(send that as the parameter), the first thing it should query is an id field having a nextIterationID of 110003. That would be the first loop.
Since the iterationCount is not 0 yet, it would keep looping. Then it would look for an id where nextIterationID is 110002 based on first loop determination, so second loop will find "id" of 110001 and return it. And since that record iterationCount = 0, it would stop the loop.
It's okay if I call the SP/function using 110003, which is the 3rd iteration, and it would not return the 110004, 4th iteration. I only need it to go back given the id.
A while ago I did this using a WITH and maybe WHILE using both somehow, but I can't recall how to do this now. I need the format returned in a way so that I can use it in a larger SELECT statements.
Here is a recursive cte solution. Let me know if it needs any tweaks.
--Throwing your table into a temp table
CREATE TABLE #yourTable (ID INT,NextIterationID INT,IterationCount INT)
INSERT INTO #yourTable
VALUES
(110001,110002,0),
(110002,110003,1),
(110003,110004,2),
(110004,1,3)
--Now for the actual work
--Here is your parameter
DECLARE #param INT = 110003;
--Recursive CTE
WITH yourCTE
AS
(
--Initial Row
SELECT ID,
NextIterationID,
IterationCount
FROM #yourTable
WHERE NextIterationID = #param
UNION ALL
--Finding all previous iterations
SELECT #yourTable.*
FROM #yourTable
INNER JOIN yourCTE
ON yourcte.ID = #yourTable.NextIterationID
--Where clause is not really necessary because once there are no more previous iterations, it will automatically stop
--WHERE yourCTE.IterationCount >= 0
)
SELECT *
FROM yourCTE
--Cleanup
DROP TABLE #yourTable
Results:
ID NextIterationID IterationCount
----------- --------------- --------------
110002 110003 1
110001 110002 0

Increment field with not null and unique constraint in PostgreSQL 8.3

I have a table "items" with a column "position". position has a unique and not-null constraint. In order to insert a new row at position x I first try increment the positions of the subsequent items:
UPDATE items SET position = position + 1 WHERE position >= x;
This results in a unique constraint violation:
ERROR: duplicate key value violates unique constraint
The problem seems to be the order in which PostgreSQL performs the updates. Unique constraints in PostgreSQL < 9.0 aren't deferrable and unfortunately using 9.0 is currently not an option. Also, the UPDATE statement doesn't support an ORDER BY clause and the following doesn't work, too (still duplicate key violation):
UPDATE items SET position = position + 1 WHERE id IN (
SELECT id FROM items WHERE position >= x ORDER BY position DESC)
Does somebody know a solution that doesn't involve iterating over all items in code?
Another table, with multiple unique index:
create table utest(id integer, position integer not null, unique(id, position));
test=# \d utest
Table "public.utest"
Column | Type | Modifiers
----------+---------+-----------
id | integer |
position | integer | not null
Indexes:
"utest_id_key" UNIQUE, btree (id, "position")
Some data:
insert into utest(id, position) select generate_series(1,3), 1;
insert into utest(id, position) select generate_series(1,3), 2;
insert into utest(id, position) select generate_series(1,3), 3;
test=# select * from utest order by id, position;
id | position
----+----------
1 | 1
1 | 2
1 | 3
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
3 | 3
(9 rows)
I created a procedure that updates position values in the proper order:
create or replace function update_positions(i integer, p integer)
returns void as $$
declare
temprec record;
begin
for temprec in
select *
from utest u
where id = i and position >= p
order by position desc
loop
raise notice 'Id = [%], Moving % to %',
i,
temprec.position,
temprec.position+1;
update utest
set position = position+1
where position=temprec.position and id = i;
end loop;
end;
$$ language plpgsql;
Some tests:
test=# select * from update_positions(1, 2);
NOTICE: Id = [1], Moving 3 to 4
NOTICE: Id = [1], Moving 2 to 3
update_positions
------------------
(1 row)
test=# select * from utest order by id, position;
id | position
----+----------
1 | 1
1 | 3
1 | 4
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
3 | 3
(9 rows)
Hope it helps.
as PostgreSQL supports full set of transactional DDL, you can easily do something like this:
create table utest(id integer unique not null);
insert into utest(id) select generate_series(1,4);
The table looks now like this:
test=# \d utest
Table "public.utest"
Column | Type | Modifiers
--------+---------+-----------
id | integer | not null
Indexes:
"utest_id_key" UNIQUE, btree (id)
test=# select * from utest;
id
----
1
2
3
4
(4 rows)
And now the whole magic:
begin;
alter table utest drop constraint utest_id_key;
update utest set id = id + 1;
alter table utest add constraint utest_id_key unique(id);
commit;
After that we have:
test=# \d utest
Table "public.utest"
Column | Type | Modifiers
--------+---------+-----------
id | integer | not null
Indexes:
"utest_id_key" UNIQUE, btree (id)
test=# select * from utest;
id
----
2
3
4
5
(4 rows)
This solution has one drawback: it needs to lock the whole table, but maybe this is not a problem here.
The 'correcter' solution might be to make the constraint DEFERRABLE
ALTER TABLE channels ADD CONSTRAINT
channels_position_unique unique("position")
DEFERRABLE INITIALLY IMMEDIATE
and then set that constraint to DEFERRED when incrementing and setting it back to IMMEDIATE once you are done.
SET CONSTRAINTS channels_position_unique DEFERRED;
UPDATE channels SET position = position+1
WHERE position BETWEEN 1 AND 10;
SET CONSTRAINTS channels_position_unique IMMEDIATE;
Variant without altering table and drop constraint:
UPDATE items t1
SET position = t2.position + 1
FROM (SELECT position
FROM items
ORDER BY position DESC) t2
WHERE t2.position >= x AND t1.position = t2.position
Online example: http://rextester.com/FAU54991