I have a table called "post". It has a column named "ID". It has to be numbered serial-wise normally, but because of some programming requirements, the column gets deranged, and at that time I need to re-number the column again, serial wise. There is no other Primary key.
I tried many methods using Cursor and Looping but to no avail.
Can anyone suggest any method. Please include details.
First you can just delete that column's data fully, tyr to execute following command:-
UPDATE table_name, (select #row_number:= 0) AS t
SET id = (SELECT #row_number := #row_number + 1);
For deleting that column's data you can simply use following command:-
UPDATE tab SET id = NULL;
Hopefully this will solve your problem.
Related
I have created a MySQL Trigger BEFORE INSERT on table name agent_mst as below
BEGIN
DECLARE max_id INT;
SET max_id=(SELECT MAX(agent_id_pk)+1 FROM `agent_mst`);
IF (max_id IS NULL) THEN
SET max_id=1;
END IF;
SET NEW.date_added=NOW(),
NEW.date_updated=NOW(),
NEW.agent_code = CONCAT('SDA', LPAD(max_id, 4,'0'));
END
So what it does is, every time we inset a record, it generates agent_code field value to something like SDA0001, SDA0002, SDA0003, ...
Now suppose I delete a record with code SDA0003 and insert new record, it will definitely generate the agent code as SDA0004. As it is taking the max_id and increasing it with 1. But here I want to get SDA0003 again. So that all agent_codes can stay in sequence. How to do that?
Thanks in advance.
you need to identify the first (smallest) missing id.
check out in this link, a nice way to do it in a select query:
Find mininum not used value in mysql table
To know next auto increment id try to run below query and check column "Auto_increment":
SHOW TABLE STATUS FROM DBName where name = 'tableName'
I am trying to use a simple MySQL query to update my table with positions.
Let's assume I have a book table with an ID, a writer_id and a position field.
I want to be able to have positions from 1 ... x , but per writer_id.
If I delete a record there will be a gap in my positions so this is why I want a simple query to reset all the positions without gaps.
Currently I have the following code (which works), but I think this should be possible a lot easier (and probably faster).
set #position := 0;
set #lastDependency := 0;
set #previousDependency := -1;
UPDATE `book` SET
`writer_id`=(#lastDependency:=`writer_id`), -- Set writer_id of current row
position=(
IF (
NOT #lastDependency=#previousDependency,
#position:=1, -- New writer_id => set position to 1
#position:=#position+1 -- Same writer id, increment position
)
),
`writer_id`=(#previousDependency:=`writer_id`) -- Set writer_id of last used row
ORDER BY `writer_id`, position ASC -- Order by current positions
I can also use PHP to loop through all my records and save them one by one, but I guess that won't be any better
why don't you use a trigger with the following function:
"when a row is deletet, reduce evere writer_id that is greater than the deleted ones by one"
or to say it in pseudo-code:
create trigger for delete...
update book
set writer_id = writer_id - 1
where writer_id > deleted.writer_id
Let me quote the MySQL documentation to you:
As a general rule, you should never assign a value to a user variable and read the value within the same statement. You might get the results you expect, but this is not guaranteed. The order of evaluation for expressions involving user variables is undefined and may change based on the elements contained within a given statement; in addition, this order is not guaranteed to be the same between releases of the MySQL Server.
So the way you attempt to do things may work, but comes with absolutely no guarantees. Therefore I'd suggest you do this in PHP instead of MySQL. Or you do it in MySQL using a stored procedure.
Is there a way in SQL (MySQL) to increment a value, and also return the value in a single query. I am trying to ovoid doing two queries like the following:
QUERY 1
UPDATE my_table SET my_col = (my_col + 1) WHERE something = something_else;
QUERY 2
SELECT my_col FROM my_table WHERE something = something_else;
Thanks.
To my knowledge there is still no such possibility in MySQL, but take a look at this question for a possible workaround that at least lets you have the select and update work with the same data transactionally.
There is no way to make a select and a update at the same time.
If you want to avoid the select you can declare a variable and put there the value, but that will put the last updated row value in the variable.
declare #value int
UPDATE my_table SET my_col = (my_col + 1), #value = (my_col + 1) WHERE something = something_else;
I don't know what scripting language you are using but here is an example on creating a stored procedure in MySQL that returns the updated value so you can update and select in one operation:
Get Updated Value in MySQL instead of affected rows
I have a need for unique identifiers in my application. To that end, I created a table in my database that only contains 1 column 'unique_id" (BIGINT) and 1 row.
The idea is to use a stored procedure to get the next identifier when I need it. I figured a 1-line operation like this would do the job:
UPDATE identifier_table SET unique_id = unique_id + 1 OUTPUT INSERTED.unique_id
Can someone confirm if this operation is atomic, or do I need to setup a lock on the table?
Thanks!
It is atomic. It is just a single update statement, and will have no problem at all with concurrency since that will be managed by the engine with update locks. You can use OUTPUT as shown, or you can do something like this:
DECLARE #unique_id bigint;
UPDATE identifier_table
SET
#unique_id = unique_id + 1,
unique_id = unique_id + 1;
SELECT #unique_id uniqueid;
If you make #unique_id an OUTPUT parameter, then you can get the value without a select statement or use it easily in another stored procedure.
I have a MySQL table of tasks to perform, each row having parameters for a single task.
There are many worker apps (possibly on different machines), performing tasks in a loop.
The apps access the database using MySQL's native C APIs.
In order to own a task, an app does something like that:
Generate a globally-unique id (for simplicity, let's say it is a number)
UPDATE tasks
SET guid = %d
WHERE guid = 0 LIMIT 1
SELECT params
FROM tasks
WHERE guid = %d
If the last query returns a row, we own it and have the parameters to run
Is there a way to achieve the same effect (i.e. 'own' a row and get its parameters) in a single call to the server?
try like this
UPDATE `lastid` SET `idnum` = (SELECT `id` FROM `history` ORDER BY `id` DESC LIMIT 1);
above code worked for me
You may create a procedure that does it:
CREATE PROCEDURE prc_get_task (in_guid BINARY(16), OUT out_params VARCHAR(200))
BEGIN
DECLARE task_id INT;
SELECT id, out_params
INTO task_id, out_params
FROM tasks
WHERE guid = 0
LIMIT 1
FOR UPDATE;
UPDATE task
SET guid = in_guid
WHERE id = task_id;
END;
BEGIN TRANSACTION;
CALL prc_get_task(#guid, #params);
COMMIT;
If you are looking for a single query then it can't happen. The UPDATE function specifically returns just the number of items that were updated. Similarly, the SELECT function doesn't alter a table, only return values.
Using a procedure will indeed turn it into a single function and it can be handy if locking is a concern for you. If your biggest concern is network traffic (ie: passing too many queries) then use the procedure. If you concern is server overload (ie: the DB is working too hard) then the extra overhead of a procedure could make things worse.
I have the exact same issue. We ended up using PostreSQL instead, and UPDATE ... RETURNING:
The optional RETURNING clause causes UPDATE to compute and return value(s) based on each row actually updated. Any expression using the table's columns, and/or columns of other tables mentioned in FROM, can be computed. The new (post-update) values of the table's columns are used. The syntax of the RETURNING list is identical to that of the output list of SELECT.
Example: UPDATE 'my_table' SET 'status' = 1 WHERE 'status' = 0 LIMIT 1 RETURNING *;
Or, in your case: UPDATE 'tasks' SET 'guid' = %d WHERE 'guid' = 0 LIMIT 1 RETURNING 'params';
Sorry, I know this doesn't answer the question with MySQL, and it might not be easy to just switch to PostgreSQL, but it's the best way we've found to do it. Even 6 years later, MySQL still doesn't support UPDATE ... RETURNING. It might be added at some point in the future, but for now MariaDB only has it for DELETE statements.
Edit: There is a task (low priority) to add UPDATE ... RETURNING support to MariaDB.
I don't know about the single call part, but what you're describing is a lock. Locks are an essential element of relational databases.
I don't know the specifics of locking a row, reading it, and then updating it in MySQL, but with a bit of reading of the mysql lock documentation you could do all kinds of lock-based manipulations.
The postgres documenation of locks has a great example describing exactly what you want to do: lock the table, read the table, modify the table.
UPDATE tasks
SET guid = %d, params = #params := params
WHERE guid = 0 LIMIT 1;
It will return 1 or 0, depending on whether the values were effectively changed.
SELECT #params AS params;
This one just selects the variable from the connection.
From: here