I am trying to update my tables data(1=>3, 2=>1, 3=>2) by swapping them using below queries.
/* Temporarily set 1 to a dummy unused value of 11
so they are disambiguated from those set to 1 in the next step */
update <tablename>
set id = 11
where id = 1
update <tablename>
set id = 1
where id = 2
update <tablename>
set id = 2
where id = 3
update <tablename>
set id = 3
where id = 11
Wondering if I can optimize my script.
You can just use case. Conceptually the operation happens "all at once" so there's no need to use a fourth dummy value as in your sequential approach.
UPDATE YourTable
SET ID = CASE ID WHEN 1 THEN 3
WHEN 2 THEN 1
WHEN 3 THEN 2
END
WHERE ID IN (1,2,3)
Though changing ids is unusual as they should generally be immutable.
Related
I have two tables Tenants and Inovices. Invoices have tenant_id column, and I need to add invoice_number incremental field by tentan_id to table Invoices.
My problem is identical to this Auto increment considering Tenant id
Actually, this solution works for me, but now I need to fill the invoice_number increment field of existing rows on table before apply the trigger in this solution.
Something like this but incrementing by tenant_id:
DECLARE #invoice_number INT
SET ##invoice_number = 0
UPDATE Invoices
SET #invoice_number = invoice_number = #invoice_number + 1
GO
How to loop and increment by each tenant?
You might use the following solution
Add a column invoice_seq in your Tenants table, so your Tenants table should look like Tenants(tenant_id,name,...,invoice_seq), so on creating the invoice, you do the following steps
Increment the invoice_seq in table InvoiceTenants
update the Invoice record by setting the invoice_number ='I' format(tenant_id,'000') + '-' + format(invoice_seq,'000000')
Here your invoice number will look like:
I001-000001 <-- tenant 1 and sequence 1
I001-000002
I001-000003 <-- tenant 1 and sequence 3
I002-000001 <-- tenant 2 and sequence 1
I003-000001 <-- tenant 3 and sequence 1
** sample code **
-- for the example below i will user #tenant = 1, the below code can be converted to stored procedure of code behind in your application
declare #invoice_seq int,
#tenant int = 1 -- here you can change the number to the way you wish
-- retrieve the last tenant +1
select #invoice_seq = invoice_seq+1 from Tenants where tenant_id=#tenant
-- add the invoice
insert into Invoices(tenant_id,invoice_number,... other columns....)
values (#tenant,'I' + format(#tenant,'000') + '-' + format(#invoice_seq,'000000'),... other columns...)
-- update the invoice_seq in the Tenants table
update Tenants set invoice_seq = #invoice_seq where tenant_id=#tenant
Hope this will help you
Hi i have a table like this:
ID Name Number
1 john 91234567
2 tom 98765432
3 ken 91357246
...
I am trying to change number [91234567] to another number but i get this single row query returns more than 1 row.
My statement:
Update table set number = '9000000' where id = (select id from table where number = '91234567')
Perhaps i have another record with the same number further down the table.
Since i do not have access to the id, how can i change my statement? Thanks.
Try to use IN instead of =
Update table
set number = '9000000'
where id IN (select id from table where number = '91234567')
If you need to change all the records containing 91234567 to 9000000:
update table
set number = 9000000
where number = 91234567
I have a table thus
ID stuff1 stuff2
1 10 cool
2 4 poor
3 8 cool
4 1 sucks
I need an sql to delete only 10 in row 1
I used->>> delete stuff1 from mytable where ID=1
This works on access db but does not work on sql server
How do I do this on SQL server???
Are you trying to delete the row, or do you just want to remove the values from column stuff1?
In case you want to delete the row:
DELETE FROM mytable where ID = 1
In case you just want to remove the value of stuff1:
-- to set it to null
UPDATE mytable SET stuff1 = NULL WHERE ID = 1
-- to set it to zero
UPDATE mytable SET stuff1 = 0 WHERE ID = 1
By delete one field, I'm guessing you really mean null the column value:
UPDATE mytable
SET stuff1 = null
WHERE ID=1
DELETE works on whole rows, not individual columns.
I have been searching around stackoverflow but I have not found what I'm looking for.
I have a Sql Server Database. One table with a field "Priority" I would like to update on every insert or update.
The problem is that I want to perform a Priority pile using this rules:
1.-If the value I try to insert has a prority value that already exists then every consecutive row in the table must change its priority value adding 1.
2.-If the value I try to insert has a priority that not exists then the trigger does nothing.
This is the trigger I haver built:
ALTER trigger [Priority]
on [dbo].[TBL_PILA]
after insert, update
AS
declare #priority int;
declare #reg_id int;
SELECT #reg_id =i.id from inserted i;
SELECT #priority =PRIORITY from TBL_PILA where ID =#reg_id
-- perform update here in TBL_PILA table
UPDATE TBL_PILA SET PRIORITY=PRIORITY+1 WHERE ID <>#reg_id AND PRIORITY>=#priority
GO
Edit: As Suggestions, I change the trigger body like this:
ALTER trigger [Priority]
on [dbo].[TBL_PILA]
after insert, update
if exists (select *
from inserted i join TBL_PILA m
on i.ID = m.ID
)
update TBL_PILA set PRIORITY = PRIORITY + 1
where exists (select * from inserted i
join TBL_PILA m
on i.ID = m.ID
where m.PRIORITY>=i.PRIORITY)
Now I have a new problem: the priority value inserted is affected by the trigger and it is added 1 too.
Does anybody knows how to increase priority values only affecting some range as I explained below?
The problem is whenever exists a few consecutive values and one not consecutive value the trigger must stops.
Example
Priority 1 2 4 5 6 8
If I try to insert a row with priority=3 the result should be:
1 2 3 4 5 6 8
Then If I try to insert a row with priority=4 then the result should be:
1 2 3 4 (inserted value) 5 (4+1) 6 (5+1) 7 (6+1) 8
But using the trigger I built I get this: 1 2 3 4 5 6 7 9 (8+1)
I have a simple table that stores stock levels. ie.
ID int PK
LocationID int
StockLevel real
There could be multiple rows in this table for each location ie:
ID | LocationID | StockLevel
----------------------------
1 | 1 | 100
2 | 1 | 124
3 | 2 | 300
In this example its trivial to see that 224 units exist at location 1.
When I come to decrement the stock level at location 1 I am using
a cursor to iterate over all rows at where LocationID is 1 and using some simple
logic decide whether the stock available at the current row will satisfy the passed in
decrement value. If the row has sufficient quantity to satisfy the requirement I decrement the rows value and break out of the cursor, and end the procedure, however if the row doesnt have sufficient quantity available I decrement its value to zero and move to the next row and try again (with the reduced quantity)
Its quite simple and works ok, but the inevitable question is: Is there a way of performing
this RBAR operation without a cursor?? I have attempted to search for alternatives but even wording
the search criteria for such an operation is painful!
Thanks in advance
Nick
ps. I am storing data in this format because each row also contains other columns that are unique, and hence cant simply be aggregated into one row for each location.
pps. Cursor Logic as requested (where '#DecrementStockQuantityBy' is the quantity that we need
to reduce the stock level by at the specified location):
WHILE ##FETCH_STATUS = 0
BEGIN
IF CurrentRowStockStockLevel >= #DecrementStockQuantityBy
BEGIN
--This row has enough stock to satisfy decrement request
--Update Quantity on the Current Row by #DecrementStockQuantityBy
--End Procedure
BREAK
END
IF CurrentRowStockStockLevel < #DecrementStockQuantityBy
BEGIN
--Update CurrentRowStockStockLevel to Zero
--Reduce #DecrementStockQuantityBy by CurrentRowStockStockLevel
--Repeat until #DecrementStockQuantityBy is zero or end of rows reached
END
FETCH NEXT FROM Cursor
END
Hope this is clear enough? Let me know if further/better explanation is required.
Thanks
You are correct sir a simple update statement can help you in this scenario I'm still trying to find a legitimate use for a cursor or while that I can't solve with CTE or set based.
After looking a little deeper into your question I will also propose an alternate solution:
Declare #LocationValue int = 1,#decimentvalue int = 20
with temp (id,StockLevel,remaining) as (
select top 1 id, Case when StockLevel - #decimentvalue >0 then
StockLevel = StockLevel - #decimentvalue
else
StockLevel = 0
end, #decimentvalue - StockLevel
from simpleTable st
where st.LocationID = #LocationValue
union all
select top 1 id, Case when StockLevel - t.remaining >0 then
StockLevel = StockLevel -t.remaining
else
StockLevel = 0
end, t.remaining - StockLevel
from simpleTable st
where st.LocationID = #LocationValue
and exists (select remaining from temp t
where st.id <> t.id
group by t.id
having min(remaining ) >0) )
update st
set st.StockLevel = t.StockLevel
from simpleTable st
inner join temp t on t.id = st.id