how to update multiple rows in oracle - sql

I would like to update multiple rows with different values for all different records, but don't have any idea how to do that, i am using below sql to update for single record but i have 200 plus records to update
update employee
set staff_no = 'ab123'
where depno = 1
i have 50 dep and within those dep i need to update 200 plus staff no. any idea.
At the moment if i just do a
select * from Departments
i can see list of all employee which needs staff no updating.
UPDATE person
SET staff_no =
CASE person_no
WHEN 112 THEN 'ab123'
WHEN 223 THEN 'ab324'
WHEN 2343 THEN 'asb324'
and so on.....
END

You should be able to use MERGE statement to do it in a single shot. However, the statement is going to be rather large:
MERGE INTO employee e
USING (
SELECT 1 as d_id, 'cd234' as staff_no FROM Dual
UNION ALL
SELECT 2 as d_id, 'ef345' as staff_no FROM Dual
UNION ALL
SELECT 3 as d_id, 'fg456' as staff_no FROM Dual
UNION ALL
... -- More selects go here
SELECT 200 as d_id, 'za978' as staff_no FROM Dual
) s
ON (e.depno = S.d_id)
WHEN MATCHED THEN UPDATE SET e.staff_no= s.staff_no

use a case expression
UPDATE employee
SET staff_no =
CASE depno
WHEN 1 THEN 'ab123'
WHEN 2 THEN 'ab321'
--...
ELSE staff_no
END
WHERE depno IN ( 1, 2 ) -- list all cases here. use a subquery if you don't want to / cannot enumerate

For conditional update, you could use multiple update statements, or use CASE expression in the SET clause.
Something like,
UPDATE table
SET schema.column = CASE
WHEN column1= 'value1' AND column2='value2' THEN
'Y'
ELSE
'N'
END
I wish you tried to search for a similar question on this site, there was a recent question and this was my answer.

If you have two tables like:
CREATE TABLE test_tab_1 (id NUMBER, name VARCHAR2(25));
CREATE TABLE test_tab_2 (id NUMBER, name VARCHAR2(25));
You can use UPDATE statement as below:
UPDATE test_tab_1
SET test_tab_1.name = (SELECT test_tab_2.name FROM test_tab_2
WHERE test_tab_1.id = test_tab_2.id);

Related

sql to update table for multiple columns.?

I have an EMP table with columns like id,name,job,salary,age,doj.
This EMP table has 10 records, with IDs id1,id2....id10.
I need a DML statement to update names for 4 IDs ( id2,id4, id6, id8).
This requires multiple where conditions.
Such as -
name=a where id=id2
name=b where id=id4.
Please suggest.
You can use a case expression. That should look like:
update emp
set name = case id
when 'id2' then 'a'
when 'id4' then 'b'
when 'id6' then 'c'
when 'id8' then 'd'
end
where id in ('id2', 'id4', 'id6', 'id8')

hive scan and select in one query

I have a hive table, say emp_details(name, dept).
In this table, I need to check if any records exists with dept = ‘a’ then select those records. If no such record is found then only I will choose records with dept = ‘b’. The source data has either 'a' or 'b' as dept value and my result set will contain either 'a' or 'b' not both.
The problem is I am bound to use only one hive query for this issue.
Calculate a_exist flag and use it for filtering:
select name, dept
from
(select name,
dept,
(count(case when dept='a' then 1 end) over()>0) as a_exist
from test_a
)a
where (a_exist and dept='a') --only a if exists
or ((NOT a_exist)and dept='b') --return b if a not exists
;

SQL Server 2014: Either selected or all values in where condition

Below is what I am trying to achieve. I have a procedure which receives employeeIds as optional arguments and stores them into a temp table (temp_table) like this
empId
-------
3432
3255
5235
2434
Now I need to run below query in 2 conditions:
1st condition: if argument is non blank then my query should be-
SELECT *
FROM DEPARTMENTS
INNER JOIN temp_table ON emp_no = empId
2nd condition: if argument is blank it will take all the rows from department table
SELECT *
FROM DEPARTMENTS
One option I can use is:
IF (#args <> '')
BEGIN
SELECT *
FROM DEPARTMENTS
INNER JOIN temp_table ON emp_no = empId
END
ELSE
BEGIN
SELECT *
FROM DEPARTMENTS
END
But I am looking for a better option where I don't need to write almost same query twice. Please help.
I recommend to stick to what you are already doing.
It is the cleanest and safest way performance wise.
Try this one
SELECT *
FROM DEPARTMENTS
WHERE (
#args <> ''
OR EXISTS (SELECT 1 FROM temp_table WHERE emp_no = empId)
)

How to write IN clause query to replace null for no value parameter

I am writing a query in which where clause have IN clause and there are large number of values in this IN clause , I want to fetch the result such that if there is no value exist in table for value given in IN clause then a raw containing 0 or null should return for that value. for example..
select age,sex,date_joining from emp where name IN ('amit','john','paul','dilip')
Now assume for this query ,data for john and paul does not exist in database then result should be like below..
21 male 21-AUG-2011
null null null
null null null
25 male 9-aug-2010
we can also have 0 instead of null if null is not possible
Thanks...
select filter.name
, emp.age
, emp.sex
, emp.date_joining
from (
values ('amit'), ('john'), ('paul'), ('dilip')
) filter(name)
left join
emp
on emp.name = filter.name
Live example at SQL Fiddle.
For older values of SQL Server, replace the line with values by:
from (
select 'amit'
union all select 'john'
union all select 'paul'
union all select 'dilip'
) filter(name)
You can also use common table expression to get this result:
;With AllEmpDetails as
(
Select [Name] from emp
UNION Select 'amit'
UNION Select 'john'
UNION Select 'paul'
UNION Select 'dilip'
)Select AllEmpDetails.Name, e2.Age, e2.Sex, e2.date_joining
from AllEmpDetails
Left Join emp e2 on e2.[Name] = AllEmpDetails.Name
In my database, I have already added details for amit and dilip so i have used UNION since you can easily get the detail about the available employees. On the other hand you can use UNION ALL with Distinct.

How do you find a missing number in a table field starting from a parameter and incrementing sequentially?

Let's say I have an sql server table:
NumberTaken CompanyName
2 Fred 3 Fred 4 Fred 6 Fred 7 Fred 8 Fred 11 Fred
I need an efficient way to pass in a parameter [StartingNumber] and to count from [StartingNumber] sequentially until I find a number that is missing.
For example notice that 1, 5, 9 and 10 are missing from the table.
If I supplied the parameter [StartingNumber] = 1, it would check to see if 1 exists, if it does it would check to see if 2 exists and so on and so forth so 1 would be returned here.
If [StartNumber] = 6 the function would return 9.
In c# pseudo code it would basically be:
int ctr = [StartingNumber]
while([SELECT NumberTaken FROM tblNumbers Where NumberTaken = ctr] != null)
ctr++;
return ctr;
The problem with that code is that is seems really inefficient if there are thousands of numbers in the table. Also, I can write it in c# code or in a stored procedure whichever is more efficient.
Thanks for the help
Fine, if this question isn't going to be closed, I may as well Copy and paste my answer from the other one:
I called my table Blank, and used the following:
declare #StartOffset int = 2
; With Missing as (
select #StartOffset as N where not exists(select * from Blank where ID = #StartOffset)
), Sequence as (
select #StartOffset as N from Blank where ID = #StartOffset
union all
select b.ID from Blank b inner join Sequence s on b.ID = s.N + 1
)
select COALESCE((select N from Missing),(select MAX(N)+1 from Sequence))
You basically have two cases - either your starting value is missing (so the Missing CTE will contain one row), or it's present, so you count forwards using a recursive CTE (Sequence), and take the max from that and add 1
Tables:
create table Blank (
ID int not null,
Name varchar(20) not null
)
insert into Blank(ID,Name)
select 2 ,'Fred' union all
select 3 ,'Fred' union all
select 4 ,'Fred' union all
select 6 ,'Fred' union all
select 7 ,'Fred' union all
select 8 ,'Fred' union all
select 11 ,'Fred'
go
I would create a temp table containing all numbers from StartingNumber to EndNumber and LEFT JOIN to it to receive the list of rows not contained in the temp table.
If NumberTaken is indexed you could do it with a join on the same table:
select T.NumberTaken -1 as MISSING_NUMBER
from myTable T
left outer join myTable T1
on T.NumberTaken= T1.NumberTaken+1
where T1.NumberTaken is null and t.NumberTaken >= STARTING_NUMBER
order by T.NumberTaken
EDIT
Edited to get 1 too
1> select 1+ID as ID from #b as b
where not exists (select 1 from #b where ID = 1+b.ID)
2> go
ID
-----------
5
9
12
Take max(1+ID) and/or add your starting value to the where clause, depending on what you actually want.