I have two tables with different dimension on column - sql

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';

Related

Count of empty values in string array in PostgreSQL

I want to check Projects column values have the same values for all the same values of PartNo and PartName columns. Projects column data type is character variyng[].
For example:
PartNo
PartName
Projects
1
3
6;5
1
3
1
3
3
2
5;5
In this case, Projects have different values (6;5) and () for the same PartName(3) and PartNo(1).
This is my query, but it does not work with empty character variyng[] in projects column!
SELECT COUNT(*) from (
select c.partno, c.partname
FROM unnest(items) as c
GROUP BY c.partno, c.partname
HAVING COUNT(distinct c.projects) > 1) as xxx
INTO errCount;
IF errCount > 0 THEN
RETURN QUERY
SELECT 0 as status, format('Projects value should be the same for all Codes of the Part No %s and Name %s',c.partno,c.partname) as message
FROM unnest(items) as c
GROUP BY c.partno, c.partname
HAVING COUNT(distinct c.projects) > 1
;
RETURN;
END IF;
In the case of two different values in projects (not empty array), it works.
you can use a query like this with
coalesce
function to convert null in array[null]
WITH tt AS (
SELECT
partno,
partname,
COALESCE ( project, ARRAY [null] ) AS pro
FROM
tab1
) SELECT
*,
COUNT ( pro ) AS num
FROM
tt
GROUP BY
partno,
partname,
pro
to create test table:
CREATE TABLE "tab1" (
"pk" serial4 primary key,
"partno" int4,
"partname" int4,
"project" varchar[]
);
INSERT INTO "tab1" (partno,partname,project) VALUES ( 1, 3, '{6,5}');
INSERT INTO "tab1" (partno,partname,project) VALUES ( 1, 3, NULL);
INSERT INTO "tab1" (partno,partname,project) VALUES ( 1, 3, NULL);
INSERT INTO "tab1" (partno,partname,project) VALUES ( 3, 2, '{5,5}');

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

How to update a database record and still keep the old values in sql

I have a sql table architecture as
SQL> desc etpro_update;
Name Null? Type
ID NOT NULL NUMBER
NAME VARCHAR2(4000)
IS_ACTIVE NUMBER
CREATED_DATE DATE
where IS_ACTIVE column has been set to default value of 1.So how can we store same data(record) into a table with column IS_ACTIVE having values 0 & 1.
So final output should looks like as below
123 test 1 2017_12_03
123 test 0 2017_12_03
If you want to create a new table with data having IS_ACTIVE as 0 or 1, then try:
create table some_table as
select * from etpro_update
where is_active in (0, 1);
If it's already existing, do INSERT using the SELECT:
insert into some_table (
id,
name,
is_active,
created_date
)
select id,
name,
is_active,
created_date
from etpro_update
where is_active in (0, 1);

Aggregate Function on multiple columns in SQL Server

I have the following data in a #temp table:
Id code Fname CompanyId FieldName Value
----------------------------------------------------------------
465 00133 JENN WILSON 1 ERA 1573
465 00133 JENN WILSON 1 ESHIFTALLOW 3658
465 00133 JENN WILSON 1 NETPAY 51560
I want to do following operation i.e
One Row will be addition on two columns i.e ERA + ESHIFTALLOW
Other Row will be subtraction & addition on three columns i.e NETPAY - ERA + ESHIFTALLOW
I had tried using case statement in SQL Server.
Following is the output required
where Field1= ERA + ESHIFTALLOW & Filed2=NETPAY - ERA + ESHIFTALLOW
Id code Fname CompanyId FieldName Value
----------------------------------------------------------------
465 00133 JENN WILSON 1 Field1 5231
465 00133 JENN WILSON 1 Filed2 46329
I had tried using SQL SERVER Case Statement but not getting proper output
SQL Query : Aggregate option in SQL Server CASE statement
I see at least 2 methods to get those results. A group by or a pivot
In the example below the 2 methods are shown.
CREATE TABLE #Temp (Id INT, code VARCHAR(5), Fname VARCHAR(20), CompanyId INT, FieldName VARCHAR(20), Value INT);
insert into #Temp (Id, code, Fname, CompanyId, FieldName, Value)
values
(465,00133,'JENN WILSON',1,'ERA',1573),
(465,00133,'JENN WILSON',1,'ESHIFTALLOW',3658),
(465,00133,'JENN WILSON',1,'NETPAY',51560);
with Q AS (
SELECT Id, code, Fname, CompanyId,
sum(case when FieldName = 'ERA' then Value end) as ERA,
sum(case when FieldName = 'ESHIFTALLOW' then Value end) as ESHIFTALLOW,
sum(case when FieldName = 'NETPAY' then Value end) as NETPAY
from #Temp
group by Id, code, Fname, CompanyId
)
select Id, code, Fname, CompanyId, 'Field1' as FieldName, (ERA + ESHIFTALLOW) as Value from Q
union all
select Id, code, Fname, CompanyId, 'Field2', (NETPAY - ERA + ESHIFTALLOW) from Q
;
with Q AS (
SELECT Id, code, Fname, CompanyId,
(ERA + ESHIFTALLOW) as Field1,
(NETPAY - ERA + ESHIFTALLOW) as Field2
FROM (SELECT * FROM #Temp) s
PIVOT ( SUM(VALUE) FOR FieldName IN (ERA, ESHIFTALLOW, NETPAY)) p
)
select Id, code, Fname, CompanyId, 'Field1' as FieldName, Field1 as Value from Q
union all
select Id, code, Fname, CompanyId, 'Field2', Field2 from Q
;
Note that SUM(VALUE) was used instead of MAX(VALUE). In this case it will yield the same results. It's just a choice really.
Building heavily on LukStorms' answer, you can use a PIVOT and an UNPIVOT to get the results you want:
CREATE TABLE #Temp
(Id INT, Code VARCHAR(5), Fname VARCHAR(20), CompanyId INT, FieldName VARCHAR(20), Value INT);
INSERT INTO #Temp
(Id, Code, Fname, CompanyId, FieldName, Value)
VALUES
(465,00133, 'JENN WILSON', 1, 'ERA', 1573),
(465,00133, 'JENN WILSON', 1, 'ESHIFTALLOW', 3658),
(465,00133, 'JENN WILSON', 1, 'NETPAY', 51560);
SELECT Id, Code, Fname, CompanyId, FieldName, Value
FROM (
SELECT Id, Code, Fname, CompanyId,
ERA + ESHIFTALLOW AS Field1,
NETPAY - ERA + ESHIFTALLOW AS Field2
FROM (
SELECT *
FROM #Temp
) AS s
PIVOT (
SUM(Value)
FOR FieldName IN (ERA, ESHIFTALLOW, NETPAY)
) AS p
) AS r
UNPIVOT (
Value
FOR FieldName IN (Field1, Field2)
) AS u
;
I have no idea whether this solution is anywhere near the most efficient, but it should work:
SELECT
BASE.*,
ERA.Value AS ERA,
ESALLOW.Value AS ESHIFTALLOW,
ERA.Value + ESALLOW.Value AS Field1,
etc...
FROM (
SELECT DISTINCT Id, code, Fname, CompanyId
FROM #TEMP ) BASE
LEFT OUTER JOIN (
SELECT Id, Value
FROM #TEMP
WHERE FieldName = 'ERA' ) ERA
ON BASE.Id = ERA.Id
LEFT OUTER JOIN (
SELECT Id, Value
FROM #TEMP
WHERE FieldName = 'ESHIFTALLOW' ) ESALLOW
ON BASE.Id = ESALLOW.Id
This gives you a simple table that has every type of value in a separate column, instead of in separate rows. This makes calculations possible.

change data when update

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;