change data when update - sql

I have two tables and when I make an insertion, I don't want to transfer data created, I want to put the sysdate. I have the next code:
create or replace procedure procedure1 as
begin
INSERT INTO tlp
(given_name,
namel,
email, sysdate)
SELECT first_name,
namel,
mail
FROM glob
WHERE ( NOT EXISTS (SELECT email
FROM tlp
WHERE glob.mail = tlp.email )
AND glob.mail IS NOT NULL )
OR ( NOT EXISTS (SELECT namel
FROM tlp
WHERE glob.namel = tlp.namel )
--AND glob.mail IS NULL
);
end procedure1;

create or replace procedure procedure1 as
begin
INSERT INTO tlp
(given_name,
namel,
email, sysdate)
SELECT first_name,
namel,
mail,
GETDATE() as sysdate
FROM glob
WHERE ( NOT EXISTS (SELECT email
FROM tlp
WHERE glob.mail = tlp.email )
AND glob.mail IS NOT NULL )
OR ( NOT EXISTS (SELECT namel
FROM tlp
WHERE glob.namel = tlp.namel )
--AND glob.mail IS NULL
);
end procedure1;

In your procedure for insert, number of columns given for table tlp is 4 and columns selected from table glob is 3.
If you want to insert sysdate for one column of table tlp, then mention the
column name and add sysdate in the select statement.
Assuming the table structure of tlp is
tlp (
given_name,
namel,
email,
date_created --if clmn name is not "date_created", then change it in the proc.
)
Now try this;
create or replace procedure
procedure1 as
begin
INSERT INTO tlp (
given_name, namel,
email, date_created
)
SELECT
first_name, namel,
mail, sysdate --note sysdate is given in select query
FROM glob
WHERE (
NOT EXISTS (
SELECT email
FROM tlp
WHERE glob.mail = tlp.email
)
AND glob.mail IS NOT NULL
) OR (
NOT EXISTS (
SELECT namel
FROM tlp
WHERE glob.namel = tlp.namel
)
--AND glob.mail IS NULL
);
end procedure1;

Related

Delete duplicate roles for SQL server

I have looked for the codes but I couldn't make the codes work in my SQL server 2017.
I need to create a stored procedure to avoid data duplication from a table and delete all the data duplicated.
I have created this code:
CREATE PROCEDURE deldupl_LSBU_Staff AS
SELECT Phone_number, COUNT(*) as CNT
FROM LSBU_Staff
GROUP BY Phone_number
DELETE FROM LSBU_Staff
WHERE Phone_number > 1;
BUT when I execute my code, it deletes all the records from the table and I do not want this. I just want to delete all the duplicated data.
I have also created another code to delete the duplicated data from the table LSBU_Staff:
SELECT ROW_NUMBER() OVER(PARTITION BY Phone_number ORDER BY Phone_number)
AS del_dupl_record
FROM LSBU_Staff
WHERE Phone_number > 1
DELETE FROM LSBU_Staff
WHERE Phone_number > 1;
And it still deletes all the data.
LSBU_Staff columns are: Staff_id, LastName, FirstName, Speciality_type and Phone_number. I chose Phone_number as its identification.
Try this. Not super elegant and can be cleaned up but should do the trick. This will keep the first of the group. If you prefer to keep the last change to "l2.Staff_id > l1.Staff_id"
--
DROP TABLE IF EXISTS LSBU_Staff
CREATE TABLE LSBU_Staff
( Staff_id INT IDENTITY(1,1)
, LastName VARCHAR(32)
, FirstName VARCHAR(32)
, Speciality_type VARCHAR(32)
, Phone_number VARCHAR(32)
)
INSERT INTO LSBU_Staff (LastName, FirstName, Speciality_type, Phone_number)
VALUES
('Stilskin', 'Rumple', 'dancer' , '305-305-3050')
, ('Lamb', 'Mary', 'shepherd' , '305-123-4567')
, ('Lamb', 'Aurthur', 'shepherd' , '305-123-4567')
, ('Fenokee', 'Okee', 'swimmer' , '305-305-3051')
SELECT * FROM LSBU_Staff
DELETE LSBU_Staff
WHERE Staff_id IN
(
SELECT Staff_id
FROM LSBU_Staff l1
WHERE EXISTS (SELECT 1 FROM LSBU_Staff l2 WHERE l2.Phone_number = l1.Phone_number
AND l2.Staff_id < l1.Staff_id)
)
SELECT * FROM LSBU_Staff
DROP TABLE IF EXISTS LSBU_Staff

Oracle SQL: in 'WITH' statement, how to do conditional select, use IF or CASE?

I have two tables:
CREATE TABLE Test_Persons_A (
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons_A
(PersonID,LastName,FirstName)
values(11,'LN_A1','FN_A1');
INSERT INTO Test_Persons_A
(PersonID,LastName,FirstName)
values(12,'LN_A2','FN_A2');
CREATE TABLE Test_Persons_B (
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons_B
(PersonID,LastName,FirstName)
values(21,'LN_B1','FN_B1');
INSERT INTO Test_Persons_B
(PersonID,LastName,FirstName)
values(22,'LN_B2','FN_B2');
commit;
But then I can't figure out how to do a conditional select for the 'WITH' that follows:
------------------------------use IF, not working ------------------------------
var TEST_TBL varchar2(20);
exec :TEST_TBL := 'test_person_A';
with Test_tbl as
(
IF UPPER(:TEST_TBL) = 'TEST_PERSONS_A' then select * from Test_Persons_A;
ELSIF UPPER(:TEST_TBL) = 'TEST_PERSONS_B' then select * from Test_Persons_B;
End if;
)
select PersonID as PID, LastName as LN, FirstName as FN
from Test_tbl tp
where tp.LASTNAME like '%1%'
------------------------------use CASE, not working ------------------------------
var TEST_TBL varchar2(20);
exec :TEST_TBL := 'test_person_A';
with Test_tbl as
(
CASE WHEN UPPER(:TEST_TBL) = 'TEST_PERSONS_A' then
select * from Test_Persons_A;
ELSE
select * from Test_Persons_B;
End
)
select PersonID as PID, LastName as LN, FirstName as FN
from Test_tbl tp
where tp.LASTNAME like '%1%';
And ultimately, can I generalize this somehow? i.e. In SQL (oracle at least) where can I assert conditional statements, and where can't I?
Use union all:
with Test_tbl as (
select *
from Test_Persons_A
where upper(:TEST_TBL) = 'TEST_PERSONS_A'
union all
select *
from Test_Persons_B
where UPPER(:TEST_TBL) = 'TEST_PERSONS_B'
)
This assumes the tables have the same columns in the same order.
If they don't have the same columns, list the specific columns you want for the remaining code, perhaps assigning NULL to columns that might not be in one of the tables.

Get all records if table type parameter is null

In Oracle, I want to get all values of column if the table valued parameter is null otherwise only the matched records.
create or replace PROCEDURE pr_Employees (
lastnames IN LastName,
rowCursor OUT SYS_REFCURSOR) IS
BEGIN
Select * from emp where lastname in (
SELECT COLUMN_VALUE FROM TABLE(lastnames)
)
Try this:
create or replace procedure pr_employees
( lastnames in lastname
, rowcursor out sys_refcursor )
is
begin
open rowcursor for
select * from emp
where lastname in
( select column_value from table(lastnames) )
or lastnames is empty;
end pr_employees;

I have two tables with different dimension on column

I have two table with different dimension on one column like this:
name varchar2(256 char)
and in table where I want to insert is
lastname varchar2(50 byte)
When I compile the next code:
INSERT INTO TCPD_PERSONEL_COPY
( FIRSTNAME,LASTNAME, EMAIL1)
SELECT NAME,GIVEN_NAME, MAIL
FROM glob
WHERE ( NOT EXISTS (SELECT EMAIL1
FROM tlp
WHERE GLOB.mail = TLP.email1 )
AND GLOB.mail IS NOT NULL )
OR ( NOT EXISTS (SELECT userid
FROM TLP
WHERE GLOB.LOGIN = TLP.userid )
AND GLOB.mail IS NULL )
AND GLOB.COUNTRY='France';
I have the next error:
SQL Error: ORA-12899: value too large for column "TEST"."TLP"."LASTNAME" (actual: 53, maximum: 50)
12899. 00000 - "value too large for column %s (actual: %s, maximum: %s)"
My question is: How I can do this insert possible, having in mind the fact as I don't have the permission to modify the structure of column with ALTER.
Well, you cannot insert 256 characters into a 50 character field, obviously. If you can't alter the table and are willing to live with the data loss, you could truncate the column's value using substr:
INSERT INTO TCPD_PERSONEL_COPY
( FIRSTNAME,LASTNAME, DEPARTMENT, TELEPHONE1, EMAIL1, USERID, DATECREATED)
SELECT SUBSTR(NAME, 1, 50), GIVEN_NAME, DEPARTMENT, PHONE, MAIL, LOGIN, SYSDATE
FROM gal
WHERE ( NOT EXISTS (SELECT EMAIL1
FROM TCPD_PERSONEL_COPY
WHERE GAL.mail = TCPD_PERSONEL_COPY.email1 )
AND GAL.mail IS NOT NULL )
OR ( NOT EXISTS (SELECT userid
FROM TCPD_PERSONEL_COPY
WHERE gAL.LOGIN = TCPD_PERSONEL_COPY.userid )
AND GAL.mail IS NULL )
AND GAL.COUNTRY='France';

INSERT INTO from SELECT: The select list for the INSERT statement contains more items than the insert list

I am still getting a weird error:
The select list for the INSERT statement contains more items than the insert list. The number of SELECT values must match the number of INSERT columns.
Code:
INSERT INTO #tab (Phone)
select t2.Phone
from
(
SELECT DISTINCT top 999 t3.Phone, MIN(t3.Ord)
FROM
(
select Phone1 as Phone, Ord from #tabTemp
union all
select Phone2 as Phone, Ord from #tabTemp
) t3
GROUP BY t3.Phone
ORDER BY MIN(t3.Ord) asc, t3.Phone
) t2
The idea is to select all phone numbers from #tabTemp with their row order. Then I wanna distinct them and insert distincted numbers into table #tab. Top 999 is here only for order by purpose, because I use it into a function (UDF).
Structures are following:
declare #tabTemp TABLE
(
Phone1 varchar(128) NULL,
Phone2 varchar(128) NULL,
Ord int
);
declate #tab TABLE
(
Phone varchar(max) NULL
);
EDITED:
FULL CODE
CREATE FUNCTION dbo.myFnc(#PID int, #VID int, #JID int, #ColumnNo int)
RETURNS #tab TABLE
(
Phone varchar(max) NULL
)
AS
BEGIN
if #PID is null and #VID is null and #JID is null
return;
if #ColumnNo is null or (#ColumnNo<>2 and #ColumnNo<>3 and #ColumnNo<>6)
return;
declare #catH int;
set #catH = dbo.fncGetCategoryID('H','tt'); -- just returning int value
declare #kvalP int;
set #kvalP = dbo.fncGetCategoryID('P','te');
declare #kvalR int;
set #kvalR = dbo.fncGetCategoryID('R','te');
declare #tabTemp TABLE
(
Phone1 varchar(128) NULL,
Phone2 varchar(128) NULL,
Ord int
);
-- finding parent subject + current one
WITH subj AS(
SELECT *
FROM Subjekt
WHERE
(ID = #PID and #PID is not null)
or
(ID = #VID and #VID is not null)
or
(ID = #JID and #JID is not null)
UNION ALL
SELECT t.*
FROM Subjekt t
INNER JOIN subj r ON r.ID = t.ID
)
INSERT INTO #tabTemp (Phone1,Phone2)
(select
(case when o.TYP1=#catH then o.TEL1 else null end) Phone1
,(case when o.TYP2=#catH then o.TEL2 else null end) Phone2
,so.POR_C
from
subj s
,SubjektPerson so
,Persons o
,recSetup idS
,recSetup idSO
,recSetup idO
where 1=1
and idO.isValid=1
and idSO.isValid=1
and idS.isValid=1
and idSO.ID0=so.ID
and idS.ID0=s.ID
and idO.ID0=o.ID
and so.ID_PERSON=o.ID
and so.ID_SUBJECT=s.ID
and (o.TYP=#kvalP or o.TYP=#kvalR)
)
INSERT INTO #tab (Phone)
select t2.Phone
from
(
SELECT DISTINCT top 999 t3.Phone, MIN(t3.Ord)
FROM
(
select Phone1 as Phone, Ord from #tabTemp
union all
select Phone2 as Phone, Ord from #tabTemp
) t3
GROUP BY t3.Phone
ORDER BY MIN(t3.Ord) asc, t3.Phone
) t2
RETURN
END
Not sure why you have distinct AND a group by on the same query. You could greatly simplify this.
INSERT INTO #tab (Phone)
SELECT top 999 t3.Phone
FROM
(
select Phone1 as Phone, Ord from #tabTemp
union all
select Phone2 as Phone, Ord from #tabTemp
) t3
GROUP BY t3.Phone
ORDER BY MIN(t3.Ord) asc, t3.Phone
Now for the error message you were receiving, it doesn't seem like it came from this block of code because the syntax is fine and the number of columns matches correctly. I suspect the error is somewhere earlier in your code.
Also, you might want to consider using temp tables instead of table variables since it seems like you have a lot of rows in these tables.
You've focussed on the wrong insert. This is the one with the mismatch:
INSERT INTO #tabTemp (Phone1,Phone2)
(select
(case when o.TYP1=#catH then o.TEL1 else null end) Phone1
,(case when o.TYP2=#catH then o.TEL2 else null end) Phone2
,so.POR_C
from
...
Two columns in the insert list, 3 columns in the subselect. I can't tell just from the naming whether POR_C was meant to end up in the Ord column or not.
On the surface, it appears you are maybe triggering a query planner bug or something. There are a number of iffy things going on:
The union all of the same table to itself
Using both group by and distinct
I'm not sure what you mean by
Top 999 is here only for order by purpose, because I use it into a function (UDF).
Do you mean this whole query is executed within a UDF? If so, are there other queries that might be giving that error?