When I delete all records from a Postgresql table and then try to reset the sequence to start a new record with number 1 when it is inserted, i get different results :
SELECT setval('tblname_id_seq', (SELECT COALESCE(MAX(id),1) FROM tblname));
This sets the current value of the sequence to 1, but the NEXT record (actually the first because there are no records yet) gets number 2!
And I can't set it to 0, because the minimum value in the sequence is 1!
When I use :
ALTER SEQUENCE tblname_id_seq RESTART WITH 1;
the first record that is inserted actually gets number 1 ! But the above code doesn't accept a SELECT as a value instead of 1.
I wish to reset the sequence to number 1 when there are no records, and the first record then should start with 1. But when there ARE already records in the table, I want to reset the sequence so that the next record that is inserted will get {highest}+1
Does anyone have a clear solution for this?
Use the three-argument form of setval to set the is_called flag to false, so that it returns the current value of the sequence for the next nextval call rather than immediately generating a new one.
http://www.postgresql.org/docs/current/interactive/functions-sequence.html
Also note you need to use COALESCE(MAX(id),0)+1, otherwise the first value from the sequence will be MAX(id), which you know to already exist. (thx Stephen Denne)
See http://www.postgresql.org/docs/current/static/functions-sequence.html, near the bottom of the page.
Specifically, at least in Postgresql 9.0, you can find and set the value of a sequence. You can use the three-argument form of setval() to set either the current value of the sequence or the next value of the sequence (which would allow you to set the sequence to 1 on the next value retrieval).
Related
I can do this using multiple commands in C# for the app I'm creating, but prefer a stored proc to eliminate issues with latency/locks, etc. (hopefully):
I have a table of 10 extensions (important fields):
SortOrder, Extension, IsUsed
First record will be set to IsUsed = true
When calling the stored proc, I need the IsUsed of the NEXT record in sort order to be set to true,the current record that is true set to false. When I hit the last record, rotate back to the first record.
Use Case: I need to rotate through a bank of usable numbers. Multiple people use the app, so cannot reuse. a number within the last 4 minutes (Bank of 10 will suffice, but we can extend if necessary). When the user requests a number, they get the next avail. I can build the table however needed, so any and all options to achieve use case are welcome.
I need to set the flag to true on the 1st record when stored proc is called. All other records should be false.
I have seen this, which is of interest, but doesn't quite answer:
Get "next" row from SQL Server database and flag it in single transaction
If all that you're using this for is to return a number to identify a session, I'd suggest scrapping the whole table idea and letting SQL Server do the work for you.
You can create a SEQUENCE object that will cycle and return the next value for you, without needing to write any code or maintain any tables.
CREATE SEQUENCE dbo.Extension
AS integer
START WITH 5
INCREMENT BY 5
MINVALUE 5
MAXVALUE 50
CYCLE;
This will return the number 5 the first time it's called, up to the number 50 on call number 10, and then start back over. You can adjust the numbers in the code to more or less do whatever you would like, though.
Get the next value like this:
SELECT NEXT VALUE FOR dbo.Extension;
And when/if you need to extend the range:
ALTER SEQUENCE dbo.Extension
MAXVALUE 100;
Play around with the idea on the Rextester demo.
Edit: In light of the comments above and below, I'd still stick with a SEQUENCE, I think.
Every time your code calls the table for an extension, use a query along the lines of this:
SELECT
Extension
FROM
ExtTable
WHERE
SortOrder = NEXT VALUE FOR dbo.Extension;
Functionally, this should do what you're after, again with no code to write or maintain.
Is there a way for me to know if the stream of rows has ended? That is, if the job is on the last row?
What im trying to do is for every 10 rows do something, my problem are the last rows, for example in 115 rows, the last 5 wont happen but i need them to.
There is no built-in functionality in Talend which tells you if you're on the last row. You can work around this using one of the following:
Get the row count beforehand. For instance, if you have a file, you
can use tFileRowCount to count the number of rows, then when you
process your file, you use a variable for your current row
number, and so you can tell if you've reached the last row. If your
data come from a database, you could either issue a query that
returns the total number of rows beforehand, or modify your main
query to return the total number of rows in an additional column and
use that (using ranking functions).
Do some processing after the subjob has ended: There may be situations
where you need a special processing for the last row, you can achieve
this by getting the last row processed by the previous subjob (which
you have already saved, for instance, by putting a tSetGlobalVar
after your target, when your subjob is done, your variable contains the last written value).
Edit
For your use case, what you could do is first store the result of the API call in memory using tHashOutput, then read it with a tHashInput in order to process it, and you'll know then how many rows you have retrieved using tHashOutput's global variable tHashOuput_X_NB_LINE.
I want to calculate the difference between the previous and the current column and make it a new column named increase. For this, I'm using the lag window function. The value of the first column is not defined since no previous column exists. I know that a 3rd parameter specifies the default value. However, it depends. For the first row, I want to use the value of another column e.g. the one of count from that current row. This assumes that 0 is increased to count for the first row which is what I need. Specifying the column name as 3rd argument for the lag function does not work correctly and neither does using 0. How can it be done? I'm getting strange results such as quite a random result or even negative numbers.
SELECT *, mycount - lag(mycount, 1) OVER (ORDER BY id, messtime ASC) AS increase FROM measurements;
Window functions cannot be nested either:
ERROR: window function calls cannot be nested
There is another issue with your query: So far your results are in random order, so you may think you are seeing problems that don't exist.
Add ORDER BY id, messtime to your query to see the rows in order. Now you can compare one row with its predecessor directly. Are there still issues? If so, which exactly?
SELECT *, "count" - lag("count", 1) OVER (ORDER BY id, messtime) AS increase
FROM measurements
ORDER BY id, messtime;
COUNT is a reserved word in SQL. It seems the DBMS thinks you want to nest COUNT and LAG somehow.
Use another column name or use quotes for the column:
SELECT *, "count" - lag("count", 1) OVER
I am using a "sequence" with start value = 1 and increment = 1 and suppose i insert 10 elements in the table then "last_value" goes to 10. now if i delete 10th element then "last_value" still points to 10. now my question is, is there any possibility that value of "last_value" may decrease to 9 by killing postgres or by taking dump and then again restoring the database (or any other case).
In my case it happened (i don't know how).please provide possible reasons for this.
There are only 2 cases, when a sequence is "decreased":
Sequence reached its MAXVALUE and is reset to MINVALUE . This can be controled with [ NO ] CYCLE in CREATE SEQUENCE
Sequence is explicitly reset with setval()
There are no other ways to get the same value from a sequence 2 times.
You can set the value of a sequence.
SELECT setval('public.sequence_name', 9, true);
However, if you need the values to be contiguous, I'm not sure that a sequence is the most appropriate way to go about that. Perhaps using rank()?
I am trying to get the maximum ID from a database table and want to show it on win form load.
I am using the following query to get the maximum ID.
SELECT ISNULL(MAX(ID),0)+1 FROM StockMain WHERE VRDATE = '2013-01-30'
Above should have to return the maximum ID of today., e.g if I this statement is excutes for the first time it will return me the Value '1'. After saving first record on ID = '1' it should give me MAX(ID) = '2'. But it returns me the value 1.
Any suggestion or solutions????
Wild guess... but what data type is VRDATE? Does it include a time component, or is it just a date?
If it includes a time component indicating when you saved the record, it won't pass the VRDATE = '2013-01-30' check, since this defaults to a time of midnight. Since the times aren't identical, they are not equal.
Instead, try:
SELECT ISNULL(MAX(ID),0)+1
FROM StockMain
WHERE VRDATE BETWEEN '2013-01-30' AND '2013-02-01'
Next question... have you considered using an IDENTITY column instead of managing the ID values manually?