SQL - Update all rows with certain condition - sql

Hi i want to do is a query which do the following thing:
If i execute the query ,all rows will set to 0 except certain id in the where(which supposed to be always 1 and only one row can be active at the moment)
tbl_menu
id | serial
starter | varchar
plate | varchar
beverage | varchar
status | smallint
So if i have one registry with status in 1 and everything else in 0, when i execute this query, certain id i choose will change to 1 and the others to 0
also only one row status = 1

Try this:
UPDATE tbl_menu
set status = CASE WHEN id = 4 or status = 1 THEN 1 ELSE 0 END;

I think you have two choices with the design as it is.
1) Do it with two easy queries.
2) Write one more complicated query with a case statement.
I personally like easy:
UPDATE tblmenu SET status = 0 WHERE status = 1;
UPDATE tblmenu SET status = 1 WHERE id = n;
Although, having said that, I think a better approach is this...
Get rid of your status column
Create a new table called, say tblstatus with one column id
One record with the id of the record
Foreign key to your main table
Now all you have to do is:
UPDATE tblstatus SET id = n;
Faster, easier, more robust...

This is a basic update statement. But if you could give more info on the column names and on what condition you want to do the updates it would be helpful.
UPDATE tbl_menu SET (column) = value
WHERE (condition)

This doesn't solve the problem of the update, but it does solve the problem of enforcing that (at most) one row is active. Use a partial unique index:
create unique index unq_menu_active on tblmenu(flag) where flag = 1;

Related

Make sure to get different results for two workers on a PostgresqlDB

I have a PostgresDB and in one table I have Server-IPs, now I want to take a bunch of workers to go and check the servers in my DBs. But I want to make sure that no two workers get the same Server-IP, so as soon as one IP is selected it should be unavailable for all the other workers.
CREATE TABLE server
(
id INT AUTO_INCREMENT,
ip VARCHAR(15) NOT NULL,
created INTEGER NOT NULL,
modified INTEGER NOT NULL
)
Sampledata
1 | 192.168.5.22 | 1476086120 | 1476086120
2 | 192.168.5.29 | 1476084147 | 1476084147
Worker 1: SELECT ip FROM server LIMIT 1 -> 192.168.5.22
Worker 2: SELECT ip FROM server LIMIT 1 -> 192.168.5.22 // but I'd rather have the result for id = 2 here, since id = 1 was already selected by Worker 1
Can anyone please point me into a good direction on how to achieve this?
The regular locking won't do, as far as I can tell, since it only applies to Insert, Update, Delete and all I do is Select.
Maybe there is a way of selecting and updating in one step, but I haven't found anything relating to that.
So some help here would be greatly appreciated.
Thanks
You could use UPDATE ... RETURNING as in the following example:
UPDATE iptable
SET processed = TRUE
WHERE id IN (SELECT id FROM iptable
WHERE NOT processed
LIMIT 1)
RETURNING ip_adress;
Here id is the primary key.
A partial index ON iptable(id) WHERE NOT processed may speed up the query.
Alternatively, you can use SELECT ... FOR UPDATE and UPDATE in one transaction:
START TRANSACTION;
SELECT id
FROM iptable
WHERE NOT processed
LIMIT 1
FOR UPDATE;
UPDATE iptable SET processed = TRUE WHERE id = ...;
COMMIT;

How to compare records and update one column

It is a little bit tricky for me so I need your help :)
I want to update the column Relevant to 0 WHERE Contract_Status_Code is 10 OR the Date_Contract_start YEAR is the same AND the Ranking_Value is lower than the other one ON all records that have the same VIN.
So I want to compare all records which have the same VIN.
Few examples to illustrate it:
I have there two records with the VIN = 123456. One of them (ID = 6847) has a higher Ranking_Value (7) than the other one (3). The YEAR is the same as well so I want to update the column relevant to 0 where the ID is 8105.
Two records with the VIN = 654321. Both of them have the same Ranking_Value but the record with the id = 11012 has the value 10 for the column Contract_Status_Code so I want to update the relevant column to 0 where the ID = 11012.
The last two records... They have the VIN = 171819. The first one (ID = 11578) has the higher Ranking_Value. But they have a different year where the contract has started. So I don't want to update both.
It is also possible that there are three or four records with the same VIN.
I hope you understand my problem. I'm from Germany so sorry for my English :)
By considering your ID column as unique or Identity column, I can suggest you the below query for your solution:
With cte
As
(Select a.Id, a.VIN From Table a
Join (Select max(Ranking_Value) ranks,VIN From Table Group By VIN, Year(Date_Contract_start)) b
on a.VIN=b.VIN And a.Ranking_Value = b.ranks)
update table
set Relevant = 0
where (Contract_Status_Code = 10) Or
ID Not In (Select id from cte)
update table1
set Relevant = 0
where Contract_Status_Code = 10
or (VIN,Year,Ranking_value) not in(
select VIN,Year,max(Ranking_Value)
from table1
group by VIN,Year
)

Get all missing values between two limits in SQL table column

I am trying to assign ID numbers to records that are being inserted into an SQL Server 2005 database table. Since these records can be deleted, I would like these records to be assigned the first available ID in the table. For example, if I have the table below, I would like the next record to be entered at ID 4 as it is the first available.
| ID | Data |
| 1 | ... |
| 2 | ... |
| 3 | ... |
| 5 | ... |
The way that I would prefer this to be done is to build up a list of available ID's via an SQL query. From there, I can do all the checks within the code of my application.
So, in summary, I would like an SQL query that retrieves all available ID's between 1 and 99999 from a specific table column.
First build a table of all N IDs.
declare #allPossibleIds table (id integer)
declare #currentId integer
select #currentId = 1
while #currentId < 1000000
begin
insert into #allPossibleIds
select #currentId
select #currentId = #currentId+1
end
Then, left join that table to your real table. You can select MIN if you want, or you could limit your allPossibleIDs to be less than the max table id
select a.id
from #allPossibleIds a
left outer join YourTable t
on a.id = t.Id
where t.id is null
Don't go for identity,
Let me give you an easy option while i work on a proper one.
Store int from 1-999999 in a table say Insert_sequence.
try to write an Sp for insertion,
You can easly identify the min value that is present in your Insert_sequence and not in
your main table, store this value in a variable and insert the row with ID from variable..
Regards
Ashutosh Arya
You could also loop through the keys. And when you hit an empty one Select it and exit Loop.
DECLARE #intStart INT, #loop bit
SET #intStart = 1
SET #loop = 1
WHILE (#loop = 1)
BEGIN
IF NOT EXISTS(SELECT [Key] FROM [Table] Where [Key] = #intStart)
BEGIN
SELECT #intStart as 'FreeKey'
SET #loop = 0
END
SET #intStart = #intStart + 1
END
GO
From there you can use the key as you please. Setting a #intStop to limit the loop field would be no problem.
Why do you need a table from 1..999999 all information you need is in your source table. Here is a query which give you minimal ID to insert in gaps.
It works for all combinations:
(2,3,4,5) - > 1
(1,2,3,5) - > 4
(1,2,3,4) - > 5
SQLFiddle demo
select min(t1.id)+1 from
(
select id from t
union
select 0
)
t1
left join t as t2 on t1.id=t2.id-1
where t2.id is null
Many people use an auto-incrementing integer or long value for the Primary Key of their tables, and it is often called ID or MyEntityID or something similar. This column, since it's just an auto-incrementing integer, often has nothing to do with the data being stored itself.
These types of "primary keys" are called surrogate keys. They have no meaning. Many people like these types of IDs to be sequential because it is "aesthetically pleasing", but this is a waste of time and resources. The database could care less about which IDs are being used and which are not.
I would highly suggest you forget trying to do this and just leave the ID column auto-increment. You should also create an index on your table that is made up of those (subset of) columns that can uniquely identify each record in the table (and even consider using this index as your primary key index). In rare cases where you would need to use all columns to accomplish that, that is where an auto-incrementing primary key ID is extremely useful—because it may not be performant to create an index over all columns in the table. Even so, the database engine could care less about this ID (e.g. which ones are in use, are not in use, etc.).
Also consider that an integer-based ID has a maximum total of 4.2 BILLION IDs. It is quite unlikely that you'll exhaust the supply of integer-based IDs in any short amount of time, which further bolsters the argument for why this sort of thing is a waste of time and resources.

SQL count query, using where clause from 2 different tables

I am new to SQL. I need to run a one-time query at a few different sites to get a count. The query needs to give me a count of all records based on a where clause. But I'm having trouble figuring out the syntax.
Here's what I tried:
SELECT COUNT(KEYS.IDXKEYID) FROM KEYS, KEYFLAGS
WHERE IDXLEVELID = 1
AND KEYFLAGS.BKEYSEVERMADE = -1
Which gave me a crazy number.
Basically, IDXKEYID is a primary key, and exists in both the KEYS and KEYFLAGS table. I want a count of all IDXKEYID records in the database that meet the above WHERE clause critera. I just want 1 simple result in 1 column/row.
COUNT
-----
12346
Thanks in advance!
SELECT COUNT(DISTINCT KEYS.IDXKEYID) -- count each key only once
FROM KEYS, KEYFLAGS
WHERE KEYS.IDXLEVELID = 1
AND KEYFLAGS.BKEYSEVERMADE = -1
AND KEYS.IDXKEYID = KEYFLAGS.IDXKEYID -- you're missing this link
Or you can write it using EXISTS
SELECT COUNT(1) -- count each key only once
FROM KEYS
WHERE KEYS.IDXLEVELID = 1
AND EXISTS (
SELECT *
FROM KEYFLAGS
WHERE KEYS.IDXKEYID = KEYFLAGS.IDXKEYID -- correlate
AND KEYFLAGS.BKEYSEVERMADE = -1)

Update with multiple rows

i am using UPDATE to update all records in the table with value from another table:
UPDATE x.ADR_TEMP SET LOCATIONID = (SELECT ID FROM x.OBJECTRELATIONSHIP WHERE PROPERTYCLASS = 'PHYSICALLOCATION')
in both tables are the same number of records. I just need to read id from one table and put them into another.
I have error: ORA-01427: single-row subquery returns more than one row
I am new in this subject and suspect that solution is very simple. Please help me
UPDATE x.ADR_TEMP SET LOCATIONID = (
SELECT ID
FROM x.OBJECTRELATIONSHIP
WHERE PROPERTYCLASS = 'PHYSICALLOCATION' AND x.ADR_TEMP.relatedKey = x.OBJECTRELATIONSHIP.relatedKey )
if your tables are related to each other with some way like this(relatedKey is a column which relates to the second table mentioned), you can try this one.(not sure or perfect)