Counter variable in SQLite - sql

I'm working on a simple todo app that has a column for each day of the week. On startup, the app checks to see if there are any incomplete tasks from before the current date. If so, they're moved to the top of the current date's column.
The app is cloud-based, but the tasks are backed up for offline mode with an SQLite db. I can easily move the tasks by updating their date property, but I need the order property of each task to increment starting at 0 to place them at the top.
I need to be able to define a count variable in SQLite alone and increment it with each update that's performed. I know this code doesn't work, but it's an easy way of explaining what needs to be done:
count = 0
UPDATE `tasks`
SET `date` = '2010-01-04',
`order` = `count`++
WHERE `date` < '2010-01-04'
I'd rather not use a temporary table or use a counter outside of SQLite, if possible.
#OMG Ponies - I'm starting to think it's just not possible all in SQLite.

I would do it with a second SQL-Statement:
UPDATE `tasks`
SET `date` = '2010-01-04',
count = ( SELECT COUNT(`task_id`) FROM `tasks` ) + 1
WHERE `date` < '2010-01-04'
Not tested but should work!

SQLite is a great tool, but I'd be surprised if this was possible using JUST SQLite. T-SQL support isn't that great within that app.
You could probably update the existing value in the record; adding or subtracting from it, but that would require the records to already be in order.

Actually, you can use addition in Sqlite - check out http://www.sqlite.org/lang_expr.html ; you just need to use an extra UPDATE statement to increment the counter and an inner query to get it again. Make sure to do this all in a Transaction or else you'll get concurrency problems.

it sounds to me that you'd like a a count column for each row. If i were you, i think you could do the call as
UPDATE `tasks`
SET
`date` = '2010-01-04',
count = count + 1
WHERE `date` < '2010-01-04'
lemme know how that works...

Related

SQL update rows with counter

I would like to know how to loop through each record in a database, and update them using a counter.
For instance, I have a large number of email fields. I would like to update them all using the pattern: 'hello+1#gmail.com', 'hello+2#gmail.com', 'hello+3#gmail.com', 'hello+4#gmail.com' ...
I tried to do this without SQL in my Rails console, but it would take too much time. Any suggestions on how to do this using SQL?
If you are using SQL server:
select <stuff>
,row_number() over (order by <something>) as row_number
from <things>
where <something>
Will do the trick. If not, let us know what you are using and we can go from there! Are you looking to put the '+Row_number' before the #? If so it should be a fairly simple matter of replacing the the '#' with '+4#' and so on.
In MySQL, you would use variables:
update table t
set email = concat('hello+', #rn := coalesce(#rn, 0) + 1, '#gmail.com');
If you have a particular ordering in mind, you can add an order by clause.

PostgreSQL select value and increment at once

I'm looking for a possible solution to the following. I have data stored in a table to keep track of a special increment number the customer wants in the DB. This is a special number they use internally.
What I would like to do is automatically increment this number in the table when I select it. So I don't have the problem of another transaction, from someone else using the system, using the same ID number.
So I want to select the current number and increment it by one at once so I don't have duplicates. How would I go about doing this if it is even possible?
UPDATE the_table
SET the_column = the_column + 1
WHERE qualifier = X
RETURNING the_column;
This ought to do the trick, with the caveat that it will return the new id rather than the old one:
UPDATE foo
SET id=nextval('foo_sequence')
WHERE ...
RETURNING *

SQL / DB2 - retrieve value and update/increment simultaniously

I'm connecting to a DB2 database and executing SQL statements.
One example of what is being done is:
select field from library/file
[program code line finishes executing]
[increment value by one]
update library/file set field = 'incremented value'
I have a need to immediately update the value while returning the value. Rather than having to wait for the script to complete, and then run a separate UPDATE statement.
The concept of what I would like to do is this:
select field from library/file; update library/file set field = (Current Value + 1); go;
Please note... this is not the common SQL database most would be familiar with, it is a DB2 database on an IBM i.
Thanks!
Consider using a DB2 SEQUENCE to manage the next available number, if this file is simply intended to have a single row storing your counter. That is what a SEQUENCE is designed to do.
To set it up, use a CREATE SEQUENCE statement.
To increment the value and retrieve, use a SEQUENCE reference expression of the form NEXT VALUE FOR sequence-name. To find out what the most recent value was, use the PREVIOUS VALUE FOR sequence-name. These expressions can be used like a regular any column expression, such as in a SELECT or INSERT statement.
Suppose, for example you want to do this for invoice numbers (and maybe your accounting department doesn't want their first invoice number to be 000001, so we will initialize it higher).
CREATE SEQUENCE InvoiceSeq
as decimal (7,0)
start with 27000; -- for example
You could get a number for a new invoice like this:
SELECT NEXT VALUE FOR InvoiceSeq
INTO :myvar
FROM SYSIBM/SYSDUMMY1;
But what is this SYSIBM/SYSDUMMY1 table? We're not really getting anything from table, so why are we pretending to do so? The SELECT needs a FROM-table clause. But since we don't need one, let's use a VALUES INTO statement.
VALUES NEXT VALUE FOR InvoiceSeq
INTO :myvar;
So that has incremented the counter, and put the value into our variable. You could use that value to INSERT into our InvoiceHeaders and InvoiceDetails tables.
Or, you could increment the counter as you write an InvoiceHeader, then use it again when writing the InvoiceDetails.
INSERT INTO InvoiceHeaders
(InvoiceNbr, Customer, InvoiceDate)
VALUES (NEXT VALUE FOR InvoiceSeq, :custnbr, :invdate);
for each invoice detail
INSERT INTO InvoiceDetails
(InvoiceNbr, InvoiceLine, Reason, Fee)
VALUES (PREVIOUS VALUE FOR InvoiceSeq, :line, :itemtxt, :amt);
The PREVIOUS VALUE is local to the particular job, so there should be no risk of another job getting the same number.
update library/file set field = field + 1;
select field from library/file;
[program code line finishes executing]
[increment value by one]
This handles the problem of another app updating the number between the time you fetch it and the time you update it. Update it and then use it. If two apps try to update simultaneously, one will wait.
A SEQUENCE object is designed exactly for this purpose, but if you are forced to keep this 'next ID' file updated, this is how I'd do it. Follow the link in the comment by #Clockwork-Muse for info on the SEQUENCE object, or try this example from V5R4.
His request is like this:
UPDATE sometable
SET somecounter = somecounter + 10,
:returnvar = somecounter + 10;
Updates and retrieves at the same time.
This is possible in MSSQL, In fact I use it alot there,
but DB2 doesnt seem to have this feature.

How can I increment a database value in SQL?

I'm facing a problem with a voting system specially in the vote up feature.
How can I make something like votes++ in the database without the need to select the last votes in single query?
UPDATE myTable
SET voteCol = voteCol + 1
WHERE id = idOfInterest;

Oracle SQL: How to read-and-increment a field

I'm refactoring the data import procedure for an enterprise application and came across a snippet I'd like to find a better solution. When importing data we have to create a unique entity for each data set and there is a counter in a field to be used to assign this id sequentially. You read the field to get the next free id and increment it afterwards to prepare for the next time.
At the moment this is done in two steps in the original app, written in 'C':
SELECT idnext FROM mytable;
UPDATE mytable SET idnext = idnext + 1;
Obviously there is a race condition here, if multiple processes do the same thing.
Edit: Important corequisite: I can not touch the database/field definition, this rules out a sequence.
We are rewriting in perl, and I'd like to do the same thing, but better. An atomic solution would be nice. Unfortunately my SQL skills are limited, so I'm turning to collective wisdom :-)
In this particular case, a sequence is the right solution as mentioned. But if in some future situation you need to both update something and return a value in the same statement, you can use the RETURNING clause:
UPDATE atable SET foo = do_something_with(foo) RETURNING foo INTO ?
If the calling code is PL/SQL, replace the ? with a local PL/SQL variable; otherwise you can bind it as an output parameter in your program.
Edit: Since you mentioned Perl, something like this ought to work (untested):
my $sth = $dbh->prepare('UPDATE mytable SET idnext = idnext + 1 returning idnext into ?');
my $idnext;
$sth->bind_param_inout(1, \$idnext, 8);
$sth->execute; # now $idnext should contain the value
See DBI.
Why not use a sequence?
Create the sequence one time, using whatever START WITH value you want:
CREATE SEQUENCE mysequence
START WITH 1
MAXVALUE 999999999999999999999999999
MINVALUE 1
NOCYCLE
NOCACHE
NOORDER;
Then in your application code at runtime you can use this statement to get the next value:
SELECT mysequence.NEXTVAL
INTO idnext
FROM DUAL;
Update: Using a sequence would be the preferred method, but since you can't change the database then I agree that using RETURNING should work for your situation:
UPDATE mytable
SET idnext = idnext + 1
RETURNING idnext
INTO mylocalvariable;
Use SELECT FOR UPDATE statement. It guarantees mutually exclusive rights to the record :
"SELECT
FOR UPDATE;
A sequence will do the job, have a look at e.g. Oracle sequences