best practice for sql scripts syntax - sql

I have sql file that contains long Inserst.
the problem is that when I want for example to edit column number12 I have to start counting the columns in the values area and its very confusing.
they looks something like :
witch is very confusing for updating since you have to find which value belongs to which column.
is there another way to write Insert script so it will be more easy to mach column with its values ? or maybe there's a tool that can help ?
maybe something like -
Insert tableName column1 = '10', column2 = '5' , column3 = 'asdsd' ....
P.S - to see the image right click on it and 'Open in new tab'

Use two lines:
INSERT INTO TABLE (COLUMN1, COLUMN2 , COLUMN3)
VALUES (Value1 , "Long Value 2", "..." );

You can use the new way of inserting records that was introduced in SQL Server 2008.
insert into #MyTable
(Column1, Column2, Column3, Column4, Column5, Column6) values
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6)
You need to keep the column names aligned with the data and when you have more lines than fit on a page you can either restart the insert or add a column comment line at an appropriate place
insert into #MyTable
(Column1, Column2, Column3, Column4, Column5, Column6) values
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
--(Column1, Column2, Column3, Column4, Column5, Column6) values
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6),
(1, 2, 3, 4, cast(6 as numeric(38,8))), 6)
You could also keep your data in an actual table and update the table instead. Use some tool to script the inserts from that table. For example generate scripts in Server Management Studio.

You don't need multiple INSERT statements - one will do.
You can use a SELECT statement with UNION to insert multiple rows:
INSERT myTable (Col1, Col2)
SELECT val1, val2 UNION
SELECT val3, val4
If you are using SQL Server 2008, the VALUES statement has an extension:
INSERT myTable (Col1, Col2)
VALUES (val1, val2),
(val3, val4)
See INSERT for SQL Server on MSDN.
If you are talking about readability, you could use something like the following (though you will end up with a very long file), and coding this up will take lots of time:
INSERT myTable (Col1, Col2)
SELECT val1, -- Col1
val2 -- Col2
UNION
SELECT val3, -- Col1
val4 -- Col2
There are no standard convention for what you want, as such scripts are meant for running in SQL, not for reading.

Related

SQL. Where condition for multiple values of column

Im looking for some hint when trying to filter for multiple values within column.
I'm interested in an "AND" condition for some values in column X (ie. statement Where Column X in (1,2,3) doesn't fulfill my needs).
Consider this example table:
I'm interested in finding COD_OPE that has both status 6 and 7. In this example i'm interested to find only COD_OPE = 3
If i use Where status in (6,7) i'll get cod_ope 1 and 6.
Any smart way to find cod_ope = 3?
Thank you!
Code for table in the example:
CREATE TABLE [TABLE] (
COD_OPE int,
STATUS int,
Observation_date int
)
INSERT INTO [TABLE] (COD_OPE, STATUS, Observation_date)
VALUES (1, 1, 2022),(1, 1, 2021), (1, 1, 2020), (1, 6, 2019), (1, 6, 2018), (2, 1, 2022), (2, 7, 2021), (2, 4, 2020), (2, 4, 2019), (2, 7, 2018), (3, 1, 2022), (3, 1, 2021), (3, 4, 2020), (3, 7, 2019), (3, 6, 2018)
select * from [TABLE]
Use aggregation:
SELECT COD_OPE
FROM [TABLE]
WHERE STATUS IN (6, 7)
GROUP BY COD_OPE
HAVING COUNT(DISTINCT STATUS) = 2;

SQL distinct window frames of given length (time period)

I have a table with several index-dates and I need to build groups of rows with maximum interval between first and last row not exceeding a specific value.
A reproducible example looks like this:
create myTable (id CHAR(1), rownr INTEGER, index DATE);
insert into myTable values ('A', 1, '2018-01-01');
insert into myTable values ('A', 2, '2018-08-01');
insert into myTable values ('A', 3, '2019-03-04');
insert into myTable values ('A', 4, '2019-09-09');
insert into myTable values ('A', 5, '2020-02-15');
insert into myTable values ('B', 1, '2020-12-31');
insert into myTable values ('B', 2, '2021-03-04');
insert into myTable values ('B', 3, '2022-01-01');
insert into myTable values ('B', 4, '2022-02-20');
I need a new Variable index_grp where the index date of all rows of the group is within 1 year. First row which index-date is farther then 1 year from current minimum index-date starts a new group (window). The desired result looks like this:
I tried windows moving functions:
select id, rownr, index
, min(index) over(partition by id order by index range between interval '1' year preceding and current row) as index_grp
from myTable;
but obviously index_grp of row A3 would be 2018-08-01 so the windows would overlap.
In Teradata-SQL there is a neat little addon to the analytical function, called "reset when", to start a new window when a given condition is met.
However, I need a ANSI-SQL solution.

Many to many comparison in SQL Server

In SQL Server the column contains some center codes in comma separated formats like
0000700118,0000700120,0000700123,0000700163.
and the values compared by same value but the center code separation order is different LIKE 0000700123,0000700118,0000700120,0000700163.
How to compare the many to many values in SQL Server. Help me anyone to resolve the issue.
To find rows which have the same values in CostElementName (with/without the same ordering):
declare #t table
(
id int identity,
CostElementGroup varchar(10),
CostElementName varchar(max)
);
insert into #t
(
CostElementGroup, CostElementName
)
values ('A', '1, 2, 3, 4, 5'), ('A', '5, 4, 3, 2, 1'),
('A', '3, 4, 5'), ('A', '3, 5, 4'),
('A', '1, 2, 3'), ('A', '1, 2');
select *
from #t as a
join #t as b on a.CostElementGroup = b.CostElementGroup and a.id <> b.id
where
--same number of elements in the comma delimited string...
len(a.CostElementName) - len(replace(a.CostElementName, ',', '')) = len(b.CostElementName) - len(replace(b.CostElementName, ',', ''))
and not exists --...without any diff
(
select ltrim(x.value)
from string_split(a.CostElementName, ',') as x
except
select ltrim(y.value)
from string_split(b.CostElementName, ',') as y
);
You should not have all the values in a single string. Try and parse the data before introducing it in the table so that you can add each element on a new line in the table as a varchar. Afterwards, it's easier to compare the entire column with a value.

SQL merge statement with multiple conditions

I have a requirement with some business rules to implement on SQL (within a PL/SQL block): I need to evaluate such rules and according to the result perform the corresponding update, delete or insert into a target table.
My database model contains a "staging" and a "real" table. The real table stores records inserted in the past and the staging one contains "fresh" data coming from somewhere that needs to be merged into the real one.
Basically these are my business rules:
Delta between staging MINUS real --> Insert rows into the real
Delta between real MINUS staging--> Delete rows from the real
Rows which PK is the same but any other fields different: Update.
(Those "MINUS" will compare ALL the fields to get equality and distinguise the 3rd case)
I haven't figured out the way to accomplish such tasks without overlapping between rules by using a merge statement: Any suggestion for the merge structure? Is it possible to do it all together within the same merge?
Thank you!
If I understand you task correctly following code should do the job:
--drop table real;
--drop table stag;
create table real (
id NUMBER,
col1 NUMBER,
col2 VARCHAR(10)
);
create table stag (
id NUMBER,
col1 NUMBER,
col2 VARCHAR(10)
);
insert into real values (1, 1, 'a');
insert into real values (2, 2, 'b');
insert into real values (3, 3, 'c');
insert into real values (4, 4, 'd');
insert into real values (5, 5, 'e');
insert into real values (6, 6, 'f');
insert into real values (7, 6, 'g'); -- PK the same but at least one column different
insert into real values (8, 7, 'h'); -- PK the same but at least one column different
insert into real values (9, 9, 'i');
insert into real values (10, 10, 'j'); -- in real but not in stag
insert into stag values (1, 1, 'a');
insert into stag values (2, 2, 'b');
insert into stag values (3, 3, 'c');
insert into stag values (4, 4, 'd');
insert into stag values (5, 5, 'e');
insert into stag values (6, 6, 'f');
insert into stag values (7, 7, 'g'); -- PK the same but at least one column different
insert into stag values (8, 8, 'g'); -- PK the same but at least one column different
insert into stag values (9, 9, 'i');
insert into stag values (11, 11, 'k'); -- in stag but not in real
merge into real
using (WITH w_to_change AS (
select *
from (select stag.*, 'I' as action from stag
minus
select real.*, 'I' as action from real
)
union (select real.*, 'D' as action from real
minus
select stag.*, 'D' as action from stag
)
)
, w_group AS (
select id, max(action) as max_action
from w_to_change
group by id
)
select w_to_change.*
from w_to_change
join w_group
on w_to_change.id = w_group.id
and w_to_change.action = w_group.max_action
) tmp
on (real.id = tmp.id)
when matched then
update set real.col1 = tmp.col1, real.col2 = tmp.col2
delete where tmp.action = 'D'
when not matched then
insert (id, col1, col2) values (tmp.id, tmp.col1, tmp.col2);

Insert into table without having to specify every column value for each row

How do I insert into a table where the number of column value supplied is different for each row. If there is no value for a column.
CREATE TABLE myTable (column1 VARCHAR(5), column2 VARCHAR(5), column3 VARCHAR(5),
column4 VARCHAR(5), column5 VARCHAR(5), column6 VARCHAR(5))
INSERT INTO myTable ('A','B','C','D'),('A','B','C'),('A','B'),('A'),
('B','C','D'),('C','D','A')
I am fully aware of having the each row inserted by using NULL for the column that is empty.
CREATE TABLE myTable (column1, column2, column3, column4, column5, column6)
INSERT INTO myTable ('A','B','C','D',NULL,NULL),('A','B','C',NULL,NULL,NULL),
('A','B',NULL,NULL,NULL,NULL),('A',NULL,NULL,NULL,NULL,NULL),
('B','C','D',NULL,NULL,NULL),('C','D','A',NULL,NULL,NULL)
Is there a way to insert each row without having to specifying the column as NULL if there column value is not supplied?
You can insert them separately:
insert into mytable (col1, col2, col3, col4) values ('A', 'B', 'C', 'D');
insert into mytable (col1, col2, col3) values ('A', 'B', 'C'), ('D', 'E', 'F');
insert into mytable (col3, col4) values ('C', 'D');