I need to make an upsert to a table.
Using Oracle.
I created a temporary table that has the same columns as the original.
I want to merge the temp one into the original but without replacing null values from the temp table, i.e:
table1:
Id, First_Name, Last_Name, Salary
123, Bob, Foo, 100
table2:
Id, First_Name, Last_Name, Salary
123, NULL, NULL, 200
After merge:
table1:
Id, First_Name, Last_Name, Salary
123, Bob, Foo, 200
I tried constructing this:
MERGE INTO t1 wu USING t2 tmp ON (wu.Id = tmp.Id) WHEN MATCHED THEN
CASE WHEN tmp.First_Name IS NOT NULL THEN
UPDATE SET wu.First_Name = tmp.First_Name
ELSE
UPDATE SET wu.First_Name = wu.First_Name
END
CASE WHEN tmp.Last_Name IS NOT NULL THEN
UPDATE SET wu.Last_Name = tmp.Last_Name
ELSE
UPDATE SET wu.Last_Name = wu.Last_Name
END
CASE WHEN tmp.Salary IS NOT NULL THEN
UPDATE SET wu.Salary = tmp.Salary
ELSE
UPDATE SET wu.Salary = wu.Salary
END
WHEN NOT MATCHED THEN
INSERT VALUES(tmp.Id, tmp.First_Name, LastName, tmp.Salary);
But I get:
ORA-00927: missing equal sign
I do not want to use PL/SQL - all from c# directly.
NVL might help.
Test case:
SQL> create table t1 (id number, first_name varchar2(10),
2 last_name varchar2(10), salary number);
Table created.
SQL> create table t2 (id number, first_name varchar2(10),
2 last_name varchar2(10), salary number);
Table created.
SQL> insert all
2 into t1 values (123, 'Bob', 'Foo', 100)
3 into t2 values (123, null, null, 200)
4 into t2 values (555, 'Little', 'Foot', 20)
5 select * From dual;
3 rows created.
Merge:
SQL> merge into t1 using t2 on (t1.id = t2.id)
2 when matched then update set
3 t1.first_name = nvl(t2.first_name, t1.first_name),
4 t1.last_name = nvl(t2.last_name , t1.last_name),
5 t1.salary = nvl(t2.salary , t1.salary)
6 when not matched then insert
7 values (t2.id, t2.first_name, t2.last_name, t2.salary);
2 rows merged.
Result:
SQL> select * from t1 order by id;
ID FIRST_NAME LAST_NAME SALARY
---------- ---------- ---------- ----------
123 Bob Foo 200
555 Little Foot 20
SQL>
Related
I want to generate a unique PrescriptionNo for each of the Prescription based on the shopid.
I have tried the following way
id PrescriptionNo Shopid Amount
1 PRES001 2 100
2 PRES002 2 200
3 PRES001 1 100
4 PRES003 2 200
select top 1 'PRES' + right('000' + CAST(ROW_NUMBER() over (order by id) + 1 AS VARCHAR(3)),3)
from prescription
where shopid = 2
order by id desc
Try this:
create table #tmp1 (id int, prescriptionno varchar(10), shopid int, amount int);
insert into #tmp1 values (1,'PRES001',2,100);
insert into #tmp1 values (2,'PRES002',2,200);
insert into #tmp1 values (3,'PRES001',1,100);
insert into #tmp1 values (4,'PRES003',2,200);
select 'PRES' + RIGHT(concat('000',ISNULL(max(right(prescriptionNo,3)),0)+1),3)
from #tmp1
where shopid = 3
=> Returns 'PRES0001'
select 'PRES' + RIGHT(concat('000',ISNULL(max(right(prescriptionNo,3)),0)+1),3)
from #tmp1
where shopid = 2
==> Returns 'PRES0004'
By using just max() allows you to use ISNULL(..,0).
I'm new to SQL Server Management Studio, let's say I have 3 columns in my tbl_product, column1 (nchar(60)), column2 (nchar(60)), and in my column3 I want its value to be the result of (column1 * column2), how can I do that?
I saw a "Formula" in the column properties, but I'm not sure how to set a formula there, here is the screenshot:
Note: let's just set the column1 & column2's datatype to nchar.
Presuming both columns are strings that represent decimals set your Formula to this:
CONVERT(decimal,column1) * CONVERT(decimal,column2)
To change how the column is displayed simply change your SELECT statements. The column data will always be "stored" as accurate as possible.
Try running this:
SELECT CAST(column3 as decimal(10,2)) As ComputedColumn FROM tbl_product
In the above statement the cast means "show me 10 digits in total, and 2 digits after the decimal point". You can change those numbers to whatever you'd like.
You can sum two columns using transact sql while defining your table.
CREATE TABLE dbo.Products
(
ProductID int IDENTITY (1,1) NOT NULL
, QtyAvailable smallint
, UnitPrice money
, InventoryValue AS QtyAvailable * UnitPrice
);
-- Insert values into the table.
INSERT INTO dbo.Products (QtyAvailable, UnitPrice)
VALUES (25, 2.00), (10, 1.5);
-- Display the rows in the table.
SELECT ProductID, QtyAvailable, UnitPrice, InventoryValue
FROM dbo.Products;
Microsoft Docs link for Specify Computed Columns in a Table
CREATE TABLE [dbo].[Test]
( [Test1] [nchar(10)] NULL,
[Test2] [nchar(10)] NULL,
[Total] AS (cast ([a] as int)+ cast( [b] as int))
) ON [PRIMARY]
GO
INSERT INTO dbo.Test ( test1, test2 ) VALUES
( '1', -- test1 - int
'2' -- test2 - int
)
SELECT * FROM dbo.Test
Results:
Test1 test2 total
1 2 3
I want to update table1 with table2 mobile number, the common column in table1 and table2 is name, but table1 name is mixed with initial, table2 only has the name.
Can anyone tell how to update table1?
I've tried this:
update table1
set table1.mobile = table2.mobile
from table1
join table2 on table1.name = table2.name
Table1
Name Mobile
abc 123
def 456
Table2
Name Mobile
abc x null
def Y Null
I want to update table1 mobile in table2 mobile
I tried
update table1 set table1.mobile=table2.mobile from table1
join table2 on table1.name=table2.name
You can do this using sub-query.
update table1 set table1.mobile = (select TOP 1 table2.mobile from table2 where table2.name = substring(table1.name, 0, charindex(' ', table1.name)))
Edit:
I did a substring on the first word of the column value. The "anil y" will now be "anil".
You can try something like below:
Create table #table1
(
name varchar(10),
mobile int
)
insert into #table1 values ('Anil', 123)
insert into #table1 values ('abc', 888)
insert into #table1 values (NULL, 321)
Create table #table2
(
name varchar(10),
mobile int
)
insert into #table2 values ('Anil y', NULL)
insert into #table2 values ('z abc', NULL)
insert into #table2 values (NULL, NULL)
Update #table2
Set #table2.mobile = #table1.mobile
from #table2, #table1
Where charindex(#table1.name, #table2.name) > 0
Select * from #table2
Output:
Anil y 123
z abc 888
NULL NULL
I have these table's:
CREATE TABLE Functions
(
id_f NUMBER (5) NOT NULL,
id_gFK NUMBER (5) NOT NULL
) ;
--id_gFK is foreign key from Salaries table
CREATE TABLE Salaries
(
id_g NUMBER (5) NOT NULL ,
g1_g1 NUMBER (6) ,
g1_g2 NUMBER (6) ,
g1_g3 NUMBER (6) ,
g2_g1 NUMBER (6) ,
g2_g2 NUMBER (6) ,
g2_g3 NUMBER (6) ,
g3_g1 NUMBER (6) ,
g3_g2 NUMBER (6) ,
g3_g3 NUMBER (6)
) ;
--g1_g1 means - grade 1, gradation 1
CREATE TABLE Employee
(
id_e NUMBER (5) NOT NULL ,
id_fFK NUMBER (5) NOT NULL ,
grade NUMBER (1) ,
gradation NUMBER (1) ,
salary NUMBER (6)
) ;
--id_fFK is foreign key from Functions table
When I am inserting an employee, everything is working, and he is taking the salary depending on that column. But, I am able to edit a salary in Salaries table.
For example:
id_g=101, g1_g1=5000....g3_g3=1200 in Salaries table
id_f=201, id_gFK=101 in Functions table
id_e=1001, id_fFK=201, grade=1, gradation=1, salary=5000 in Employee table (5000 was taken from Salaries table depending on id_fFK, grade and gradation).
After I will edit that salary, 5000, in Salaries table, for example, 4000, I want this edit to be done automaticaly in Employee table.
I am sure that I can do this with a trigger. I have tried, but nothing.
Can anyone tell me what kind of trigger I have to use and how?
Thank you!!!
Please see the below example where am updating and inserting a record to emp_sal table and the same is getting inserted to employee table via trigger.
CREATE OR REPLACE TRIGGER change_salary
AFTER INSERT OR UPDATE ON emp_sal
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO Employee (employee_id,first_name,salary)
values (:new.eno,:new.ename,:new.sal);
END IF;
IF UPDATING THEN
UPDATE Employee
SET salary = nvl(:NEW.sal,:old.sal)
WHERE employee_id = :new.eno;
end if;
END;
Execution:
SQL> select sal from emp_sal where eno = 3 ;
SAL
----------
80006
SQL> select salary from employee where employee_id = 3;
SALARY
----------
50000
SQL> update emp_sal
set sal = 1234
where eno = 3 ;
1 row updated.
SQL> commit;
Commit complete.
SQL> select sal from emp_sal where eno = 3 ;
SAL
----------
1234
SQL> select salary from employee where employee_id = 3;
SALARY
----------
1234
SQL> insert into emp_sal(eno,ename,sal)
values
(9,'XING',40000);
1 row created.
SQL> commit;
Commit complete.
SQL> select salary from employee where employee_id =9;
SALARY
----------
40000
EDIT: Am not sure what is your trigger but i do see that there is wrong data set up. I read your requirement and did my way and it working and tested. See below:
Tables with data:
CREATE TABLE Salaries
(
id_g NUMBER (5) NOT NULL PRIMARY KEY ,
g1_g1 NUMBER (6) ,
g1_g2 NUMBER (6) ,
g1_g3 NUMBER (6) ,
g2_g1 NUMBER (6) ,
g2_g2 NUMBER (6) ,
g2_g3 NUMBER (6) ,
g3_g1 NUMBER (6) ,
g3_g2 NUMBER (6) ,
g3_g3 NUMBER (6)
) ;
Insert into SALARIES
Values
(101, 5000, 2000, 3000, 4000,
6000, 7000, 8000, 6000, 12000);
COMMIT;
--------------------------------
CREATE TABLE Functions
(
id_f NUMBER (5) NOT NULL,
id_gFK NUMBER (5) NOT NULL PRIMARY KEY,
CONSTRAINT fk_sal
FOREIGN KEY (id_gFK)
REFERENCES Salaries(id_g)
) ;
Insert into FUNCTIONS
(ID_F, ID_GFK)
Values
(201, 101);
COMMIT;
--------------------------
CREATE TABLE Employees
(
id_e NUMBER (5) NOT NULL ,
id_fFK NUMBER (5) NOT NULL ,
grade NUMBER (1) ,
gradation NUMBER (1) ,
salary NUMBER (6),
CONSTRAINT fk_id_emp
FOREIGN KEY (id_fFK)
REFERENCES Functions(id_gFK)
) ;
Insert into EMPLOYEES
(ID_E, ID_FFK, GRADE, GRADATION, SALARY)
Values
(101, 101, 1, 1, 5000);
COMMIT;
Trigger:
CREATE OR REPLACE TRIGGER change_salary_new
AFTER UPDATE ON Salaries
FOR EACH ROW
BEGIN
UPDATE Employees
SET salary = nvl(:NEW.g1_g1,:old.g1_g1)
WHERE id_e = :new.id_g;
End ;
Execution :
SQL> select id_g,g1_g1 from Salaries;
ID_G G1_G1
---------- ----------
101 5000
SQL> select id_e,salary from Employees;
ID_E SALARY
---------- ----------
101 5000
SQL> update Salaries set g1_g1 = 10202 where id_g = 101;
1 row updated.
SQL> commit;
Commit complete.
SQL> select id_e,salary from Employees;
ID_E SALARY
---------- ----------
101 10202
I am using c# and SQL Server 2008.
I have table like this
id | propertyTypeId | FinishingQualityId | title | Description | features
1 1 2 prop1 propDEsc1 1,3,5,7
2 2 3 prop2 propDEsc2 1,3
3 6 5 prop3 propDEsc3 1
4 5 4 prop4 propDEsc4 3,5
5 4 6 prop5 propDEsc5 5,7
6 4 6 prop6 propDEsc6
and here is my stored code (search in the same table)
create stored procdures propertySearch
as
#Id int = null,
#pageSize float ,
#pageIndex int,
#totalpageCount int output,
#title nvarchar(150) =null ,
#propertyTypeid int = null ,
#finishingqualityid int = null ,
#features nvarchar(max) = null , -- this parameter send like 1,3 ( for example)
begin
select
row_number () as TempId over( order by id) ,
id, title, description,
propertyTypeId, propertyType.name,
finishingQualityId, finishingQuality.Name,
freatures
into #TempTable from property
join propertyType on propertyType.id= property.propertyTypeId
join finishingQuality on finishingQuality.id = property.finishingQualityId
where
property.id = isnull(#id,property.id ) and proprty.PropertyTypeId= isnull(#propertyTypeid,property.propertyTypeId)
select totalpageconunt = ((select count(*) from #TempTable )/#pageSize )
select * from #TempTable where tempid between (#pageindex-1)*#pagesize +1 and (#pageindex*#pageSize)
end
go
I can't here filter the table by feature I sent. This table has too many rows I want to add to this stored code to filter data for example when I send 1,3 in features parameter I want to return row number one and two in the example table I write in this post (want to get the data from table must have the feature I send)
Many thanks for every one helped me and will help
Sending a delimited list of values to match with a delimited value in a column will generally get you into trouble as the only way to do it is to split each value out from the string. (Also why indexing them is pointless)
You should create an additional table containing the id from your property table & a row for each feature;
property_id feature
----------- -------
5 5
5 7
Then matching is much simpler. You can send the procedure the list of features you want to match ideally using a table valued parameter or alternatively a table function.