How to define T-SQL variables in Insert statement - tsql

I have this example insert statement that used to work for copying matching rows from Table2 to Table1:
INSERT INTO Table1 SELECT * FROM Table2 WHERE ID='555'
When this statement was working, both tables had the same three columns, FirstName, LastName, and EmailAddr1.
I've since added a column, EmailAddr2, to Table1 that doesn't appear in Table2 and I want to make sure that my modified insert statement will work as I expect.
Will this accomplish my goal?
SELECT #EmailAddr2 = 'bill#mail.gov'
INSERT INTO Table1 SELECT FirstName, LastName, EmailAddr1, #EmailAddr2
FROM Table2 WHERE ID='555'

You should do:
declare #emailAddr2 varchar(50)
set #emailAddr2 = 'Bill#mail.gov'
Insert into Table1 ( firstname, lastname, emailaddr1, emailaddr2 )
select firstname, lastname, emailaddr1, #emailAddr2
from table2 where id = '555'

Related

How to filter out updated records from CTE in postgres?

I am trying to perform an update and insert operation on a partitioned table using the same CTE. The update query works perfectly fine. But during insert, I just want those records from CTE which were not updated so that I can make an optimal insert with least cost.
Below is my table and query :
create table scientist (id integer, firstname varchar(100), lastname varchar(100));
insert into scientist (id, firstname, lastname) values (1, 'albert', 'einstein');
insert into scientist (id, firstname, lastname) values (2, 'isaac', 'newton');
insert into scientist (id, firstname, lastname) values (3, 'marie', 'curie');
select * from scientist;
alter table scientist add constraint id_pk PRIMARY KEY ("id");
with temp(id, firstname, lastname) as (
Select *
from (values(1, 'albert','besra'),
(5, 'abc', 'def')
) as a(id, firstname, lastname)
),
updated as(
update scientist s
set lastname = t.lastname
from temp t
where s.id = t.id returning t.*
)
Select *
from updated;
At present, it is returning all the rows. I was able to filter out records which were updated but that increased the total cost of my operation.
where not exists (Select 1 from updated where updated.id = temp.id )
Is there a way I can do that ?

Conditionally insert from one table into another

The same name may appear in multiple rows of table1. I would like to enumerate all names in sequential order 1, 2, ... One way to do so is to
create new table with name as primary key and id as serial type.
Select name from table1 and insert it into table2 only when it doesn't exist
table1 (name vchar(50), ...)
table2 (name vchar(50) primary key, id serial)
insert into table2(name)
select name
from table1 limit 9
where not exists (select name from table2 where name = table1.name)
This doesn't work. How to fix it?
Just select distinct values:
insert into table2(name)
select distinct name
from table1
order by name;

How to execute multiple query one by one

table_1 (id, first_Name, last_Name)
table_2 (id, name, table_1_id)
My work is to copy all values of a column from table_1 to table_2 as individual entry. My query is
Query_1:
insert into table_2 ( name, table_1_id )
select first_Name as name, id as table_1_id from table_1.
My other query is
Query_2:
insert into table_2 ( name, table_1_id )
select last_Name as name, id as table_1_id from table_1.
It run pretty good but save all first_name then save all last_name.
my requirement is to run these two queries together and want the result will be like
first_Name(whatever) table_1_id (1)
last_Name(whatever) table_1_id(1)
first_Name(whatever) table_1_id(2)
last_Name(whatever) table_1_id(2)
Thanks in advance
Note: table_1_id is not a foreign key in table_2
Try by using WITH Queries (Common Table Expressions)
WITH cte AS (
insert into table_2 ( name, table_1_id )
select first_Name as name, id as table_1_id from table_1
)
insert into table_2 ( name, table_1_id )
select last_Name as name, id as table_1_id from table_1
and test values by select * table_2 order by table_1_id
You can achieve this using an union all:
INSERT INTO table_2( name, table1_id)
select name, id from
(
select first_name as name, id from table_1
union all
select last_name as name, id from table_1
) A
order by id

How to use Common Table Expression with parameters?

I have a stored procedure with 2 CTEs. The second CTE has a parameter
WITH path_sequences
AS
(
),
WITH categories
AS
(
... WHERE CategoryId = #CategoryId
// I dont know how to get this initial parameter inside the CTE
)
SELECT * FROM path_sequences p
JOIN categories c
ON p.CategoryId = c.CategoryId
The initial parameter that I need to get inside the second TCE is p.CategoryId. How do I do that without having to create another stored procedure to contain the second CTE?
Thanks for helping
You can create table valued function
create function ftCategories
(
#CategoryID int
)
returns table
as return
with categories as (
... WHERE CategoryId = #CategoryId
)
select Col1, Col2 ...
from categories
and use it as
SELECT *
FROM path_sequences p
cross apply ftCategories(p.CategoryId) c
I have created simple query using your code. You can use it like -
DECLARE #CategoryId INT
SET #CategoryId = 1
;WITH path_sequences
AS
(
SELECT 1 CategoryId
),
categories
AS
(
SELECT 1 CategoryId WHERE 1 = #CategoryId
)
SELECT * FROM path_sequences p
JOIN categories c
ON p.CategoryId = c.CategoryId
This syntax is for External Aliases:
-- CTES With External Aliases:
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
-- Define the CTE query.
(
SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
)
The only way to add parameters is to use scope variables like so:
--Declare a variable:
DECLARE #category INT
WITH
MyCTE1 (exName1, exName2)
AS
(
SELECT <SELECT LIST>
FROM <TABLE LIST>
--Use the variable as 'a parameter'
WHERE CategoryId = #CategoryId
)
First remove the second WITH, separate each cte with just a comma. Next you can add parameters like this:
DECLARE #category INT; -- <~~ Parameter outside of CTEs
WITH
MyCTE1 (col1, col2) -- <~~ were poorly named param1 and param2 previously
AS
(
SELECT blah blah
FROM blah
WHERE CategoryId = #CategoryId
),
MyCTE2 (col1, col2) -- <~~ were poorly named param1 and param2 previously
AS
(
)
SELECT *
FROM MyCTE2
INNER JOIN MyCTE1 ON ...etc....
EDIT (and CLARIFICATION):
I have renamed the columns from param1 and param2 to col1 and col2 (which is what I meant originally).
My example assumes that each SELECT has exactly two columns. The columns are optional if you want to return all of the columns from the underlying query AND those names are unique. If you have more or less columns than what is being SELECTed you will need to specify names.
Here is another example:
Table:
CREATE TABLE Employee
(
Id INT NOT NULL IDENTITY PRIMARY KEY CLUSTERED,
FirstName VARCHAR(50) NOT NULL,
LastName VARCHAR(50) NOT NULL,
ManagerId INT NULL
)
Fill table with some rows:
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Donald', 'Duck', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Micky', 'Mouse', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Daisy', 'Duck', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Fred', 'Flintstone', 5)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Darth', 'Vader', null)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Bugs', 'Bunny', null)
INSERT INTO Employee
(FirstName, LastName, ManagerId)
VALUES
('Daffy', 'Duck', null)
CTEs:
DECLARE #ManagerId INT = 5;
WITH
MyCTE1 (col1, col2, col3, col4)
AS
(
SELECT *
FROM Employee e
WHERE 1=1
AND e.Id = #ManagerId
),
MyCTE2 (colx, coly, colz, cola)
AS
(
SELECT e.*
FROM Employee e
INNER JOIN MyCTE1 mgr ON mgr.col1 = e.ManagerId
WHERE 1=1
)
SELECT
empsWithMgrs.colx,
empsWithMgrs.coly,
empsWithMgrs.colz,
empsWithMgrs.cola
FROM MyCTE2 empsWithMgrs
Notice in the CTEs the columns are being aliased. MyCTE1 exposes columns as col1, col2, col3, col4 and MyCTE2 references MyCTE1.col1 when it references it. Notice the final select uses MyCTE2's column names.
Results:
For anyone still struggling with this, the only thing you need to is terminate your declaration of variables with a semicolon before the CTE. Nothing else is required.
DECLARE #test AS INT = 42;
WITH x
AS (SELECT #test AS 'Column')
SELECT *
FROM x
Results:
Column
-----------
42
(1 row affected)

postgresql calling column with same name

I have two tables, where they have the same ID name (I cannot change the way the tables are designed) and I'm trying to query table2's ID, how would I do this when they are joined?
create table table1(
id integer, -- PG: serial
description MediumString not null,
primary key (id)
);
create table table2 (
id integer, -- PG: serial
tid references table1(id),
primary key (id)
);
So basically when they're joined, two columns will have the same name "id" if I do the following query
select * from table1
join table2 on table1.id = table2.tid;
Alias the columns if you want both "id"s
SELECT table1.id AS id1, table2.id AS id2
FROM table1...
If you want to query all * on both tables but still be able to reference a specific id you can do that too, you will end up with duplicate id columns that you probably won't use, but in some situations if you really need all the data, it's worth it.
select table1.*, table2.*, table1.id as 'table1.id', table2.id as 'table2.id'
from ...
You cannot select it using select *.
try this :
select table1.id, table1.description, table2.id, table2.tid
from table1
inner join table2
on table1.id = table2.tid