How can insert a subquery into the table using Declare - sql-server

I am trying to code and run a full table so it can run sucessfully without error.
I am also making the sql table, by using Address and Person Table.
Here is the error
Msg 102, Level 15, State 1, Line 159
Incorrect syntax near '='.
/*
Foundation Lab
Creating Objects in SQL
Purpose: Create objects in SQL and set all the properties to achieve a robust well performing database: tables, views, sequences
Each comment describes a task
Write SQL statement(s) for the task under the comment
The script must be able to run repeatedly (which is why you will need to drop tables so that you can recreate them)
The SQL script meu be able to run completely and correctly on another database.
*/
/*
Tidy up any previous runs by dropping (deleting) any objects that this script creates.
Use the IF EXISTS clause for brevity.
*/
/*
Drop an existing table "Address"
Drop an existing View "AddressView"
Drop an existing table "Person"
Drop an existing view "Person"
*/
DROP TABLE IF EXISTS [dbo].[Person]
DROP TABLE IF EXISTS [dbo].[Address]
DROP VIEW IF EXISTS[dbo].[PersonView]
DROP VIEW IF EXISTS [dbo].[AddressView]
GO
/*
Create an Address table with columns:
AddressKey INT
HouseNumber INT
StreetName VARCHAR(100)
PostCode VARCHAR(8)
Set the AddressKey column as the primary key
Set the AddressKey column as an identity column
All columns must be not NULL
*/
/*
Add three rows to the table for the addresses
with the following values for HouseNumber, StreetName and PostCode
*/
CREATE TABLE Address
(
AddressKey INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
HouseNumber INT NOT NULL,
StreetName VARCHAR(100) NOT NULL,
PostCode VARCHAR(8) NOT NULL
);
/*
Add three rows to the table for the addresses
with the following values for HouseNumber, StreetName and PostCode
32, 'Acacia Avenue', 'SL1 1AA'
52, 'Cambray Road', 'SW12 9ES'
10, 'Downing Street', 'SW1A 2AA'
Use a single statement, not three statements
*/
INSERT INTO Address
(
HouseNumber,
StreetName,
PostCode
)
VALUES
(10, 'Downing Street', 'SW1A 2AA'),
(52, 'Cambray Road', 'SW12 9ES'),
(32, 'Acacia Avenue', 'SL1 1AA');
-- Check that the data in the Address tables is as expected
SELECT *
FROM Address;
/*
Create a view, named AddressView, that has HouseNumber and PostCode columns only
*/
GO
CREATE VIEW AddressView
AS
SELECT HouseNumber,
PostCode
FROM Address;
GO
-- Check the view works as expected.
SELECT *
FROM AddressView;
/*
Create a Person table with columns:
PersonKey INT
AddressKey INT
FirstName VARCHAR(100),
LastName VARCHAR(100)
DateOfBirth DATE
Set the PersonKey column as the primary key.
Set the PersonKey column as an identity column
All columns must be NOT NULL.
*/
CREATE TABLE Person
(
Personkey INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
AddressKey INT NOT NULL,
FirstName VARCHAR(100) NOT NULL,
LastName VARCHAR(100) NOT NULL,
DateofBirth DATE NOT NULL
);
-- Check that the rows are now in the Person table
SELECT *
FROM Person;
/*
Create a foreign key relationship
so that AddressKey in the Person table references the AddressKey column in the Address table.
*/
--ALTER TABLE Person ADD FOREIGN KEY (AddressKey) REFERENCES Address (AddressKey);
ALTER TABLE Person
ADD
FOREIGN KEY (AddressKey) REFERENCES Address (AddressKey);
/*
Add two sample rows to the table
* Boris Johnson in Downing Street (use variables)
* Theresa May in Cambray Road (use a SQL sub query)
*/
--'1959-01-19')
DECLARE #AddressKeyPM INT;
SELECT #AddressKeyPM = a.AddressKey FROM Address a WHERE a.PostCode = 'SW1A 2AA' AND a.HouseNumber = 10;
SELECT #AddressKeyPM
INSERT INTO Person
(
AddressKey,
FirstName,
LastName,
DateofBirth
)
VALUES
(#AddressKeyPM, 'Boris', 'Johnson', '1964-06-19');
INSERT INTO Person
(
AddressKey,
FirstName,
LastName,
DateofBirth
)
VALUES
(#AddressKeyPM = a.AddressKey FROM AddressKey a WHERE a.Postcode = 'SL1 1AA' AND a.HouseNumber = 32, 'Theresa', 'May', '1956-10-01');
-- Check that the Person table now has these two rows of data.
SELECT *
FROM Person;
/*
Show that the foreign key constraint is active
Try insert a row with a value for Addresskey that is not in the Address table
e.g. Kier Starmer, born on '1963-01-19', with AddressKey 12345
Note the error message
*/
/*INSERT INTO Person
(AddressKey, FirstName, LastName, DateofBirth)
VALUES
('12345', 'Kier', 'Starmer', '1963-01-19');
*/
-- It won't work because it needed updating with the main table with is the address table. --
-- Create a PersonView view that the FirstName and LastName (but not the DateOfBirth)
GO
CREATE VIEW PersonView
AS
SELECT FirstName,
LastName
FROM Person;
GO
/*
Opens the person view before altering
*/
SELECT *
FROM PersonView;
GO
-- Extend the view to include the House Number and PostCode from the Address table
SELECT * FROM Address a INNER JOIN Person p on p.AddressKey = a.AddressKey
GO
-- Alter the view to show only Boris and Theresa First, Last, HouseNumber and Postcode
Alter VIEW dbo.PersonView
AS
SELECT p.FirstName, p.LastName, a.HouseNumber, a.PostCode
FROM Person p INNER JOIN Address a on p.AddressKey = a.AddressKey
-- Check that the view is working correctly
GO
SELECT *
FROM PersonView;
So If you would like to teach me how to correct and fix the coding, then that would be great!

If you want to write a sub query then you can try this
INSERT INTO Person
(
AddressKey,
FirstName,
LastName,
DateofBirth
)
SELECT a.AddressKey, 'Theresa', 'May', '1956-10-01' FROM Address a WHERE a.PostCode = 'SL1 1AA' AND a.HouseNumber = 32;

Try this:
INSERT INTO Person
SELECT
AddressKey = (SELECT AddressKey FROM Address WHERE Postcode = 'SW1A 2AA' AND HouseNumber = 10)
, FirstName = 'Boris'
, LastName = 'Johnson'
, DateofBirth = '1964-06-19'
;
INSERT INTO Person
SELECT
AddressKey = (SELECT AddressKey FROM Address WHERE Postcode = 'SL1 1AA' AND HouseNumber = 32)
, FirstName = 'Theresa'
, LastName = 'May'
, DateofBirth = '1956-10-01'
;

Related

Filter out one to one relationships

I have the following table
CREATE TABLE Advisors (
AdvisorID int not null IDENTITY(1,1) PRIMARY KEY,
FirstName varchar(50) not null,
LastName varchar(50) not null,
);
CREATE TABLE Students (
StudentID int not null IDENTITY(1,1) PRIMARY KEY,
AdvisorID int FOREIGN KEY REFERENCES Advisors(AdvisorID),
FirstName varchar(50) not null,
LastName varchar(50) not null,
);
INSERT INTO Advisors (FirstName,LastName) VALUES ('Joy', 'Frank');
INSERT INTO Advisors (FirstName,LastName) VALUES ('Franklin', 'Johnson');
INSERT INTO Advisors (FirstName,LastName) VALUES ('Mary', 'Ronald');
INSERT INTO Students (FirstName, LastName, AdvisorID) VALUES ('Danny', 'Sean', 3);
INSERT INTO Students (FirstName, LastName, AdvisorID) VALUES ('Ashford', 'combs', 1);
INSERT INTO Students (FirstName, LastName, AdvisorID) VALUES ('George', 'Stoute', 3);
INSERT INTO Students (FirstName, LastName, AdvisorID) VALUES ('Ben', 'Johnson', 3);
I am trying to write a query that will filter out any advisor with more than one student
My query:
SELECT Students.StudentID, Students.FirstName, Students.LastName, Advisors.AdvisorID, Advisors.FirstName,Advisors.LastName
FROM Students
LEFT JOIN Advisors ON Students.AdvisorID = Advisors.AdvisorID
WHERE Students.AdvisorID <= 2
I am doing it wrong. My query does filter out the advisors with more than one student because I know which Advisor ID has one student.
I am trying to filter out one too many relationships and have the one too one relationship in the results
select AdvisorID
from students
group by AdvisorID
having count(s.StudentID) <= 1
Thanks for helping me out, I got the answer to my question
SELECT Advisors.AdvisorID,Students.TotalStudentsAssigned, Advisors.FirstName + ' ' +
Advisors.LastName AS AdvisorName
FROM Advisors
INNER JOIN
(
SELECT adv.AdvisorID, COUNT(*) AS TotalStudentsAssigned
FROM Advisors adv
LEFT JOIN Students s
ON adv.AdvisorID = s.AdvisorID
GROUP BY adv.AdvisorID
HAVING COUNT(*) < 2
) Students
ON Advisors.AdvisorID = Students.AdvisorID;

How to get a column derived from joining on inserted value?

For the following example I set shipping method to 'UPS'
CREATE TABLE [dbo].[Customer] (CustomerID int primary key, ShipMethodRef INT)
INSERT INTO [dbo].[Customer] VALUES (5497, 20);
CREATE TABLE [dbo].ShipMethod(ShipMethodID int PRIMARY KEY, Name varchar(10));
INSERT INTO [dbo].ShipMethod VALUES (20, 'Fedex'), (21, 'UPS')
UPDATE [dbo].[Customer]
set ShipMethodRef = CASE WHEN EXISTS (SELECT ShipMethodID from [dbo].[ShipMethod]
WHERE [dbo].[ShipMethod].Name = 'UPS')
THEN (SELECT ShipMethodID from [dbo].[ShipMethod]
WHERE [dbo].[ShipMethod].Name = 'UPS')
ELSE curTable.ShipMethodRef END
OUTPUT ShipMethod.Name as ShipMethodName
FROM [dbo].[Customer] curTable
JOIN [dbo].ShipMethod ShipMethod ON curTable.ShipMethodRef = ShipMethod.ShipMethodID
WHERE CustomerID=5497;
The OUTPUT clause returns Fedex - How can I change it to reflect the post insert state that the customer's shipping method is 'UPS' (as their shipping method Id is now 21)?
I don't think this can be done with a single statement except in the way Martin showed in his comment, but you can get the output from inserted into a table variable or a temporary table and then select from that joined to the translation tables.
Here's how I would do that (note the update statement is simplified):
DECLARE #UpdatedIds AS TABLE (ShipMethodID int);
UPDATE [dbo].[Customer]
SET ShipMethodRef = COALESCE((
SELECT ShipMethodID
FROM [dbo].[ShipMethod]
WHERE [dbo].[ShipMethod].Name = 'UPS'
), ShipMethodRef)
OUTPUT inserted.ShipMethodRef INTO #UpdatedIds
FROM [dbo].[Customer]
WHERE CustomerID=5497;
SELECT SM.ShipMethodID, SM.Name
FROM [dbo].ShipMethod AS SM
JOIN #UpdatedIds AS Updated
ON SM.ShipMethodID = Updated.ShipMethodID

SQL: How do I insert data from one table and output to a temporary table with extra value from first table

I can use the OUTPUT keyword of the insert statement to insert new data to a table and output to a temporary table.
The input table which to be inserted into another table have an Id I need to pass to the temporary table but not the table I going to insert into. This temporary table will later have to use to do extra insertion to the other table.
INSERT INTO table1 (Name, Age)
OUTPUT inserted.Id, User.Id (??) INTO TemporaryTable
SELECT Name, Age FROM User
Is there a way to do it? Because the next insertion will need the new table1.Id with the User.Id, so I can migrate some data.
Instead of using the Temporary table you can use Variable so that it will not occupy more memory.
create table table1
(
id int NOT NULL,
,name varchar(50)
,age int,
PRIMARY KEY (id)
)
insert into table1 (name,age) values ('name', 10)
declare #extracolumn as int = scope_identity()
select #extracolumn
use this #extracolumn in next insert operation.
Have you included the extra column in the schema of the temporary table?
create table table1
(
id int
,name varchar(50)
,age int
)
declare #TemporaryTable table -- or Create table #TemporaryTable
(
id int,
userid int -- defining the extra column
);
declare #extracolumn as int = 100;
-- or declare #extracolumn as int = (select value from table where condition)
-- note that subqueries cannot be added directly in the output clause
-- so need to declare and set a variable that holds the value
insert into table1
output inserted.id,#extracolumn into #TemporaryTable -- or #TemporaryTable
values(1,'name',10)
select * from #TemporaryTable
Output is
id userid
1 100

MS SQL insert into two tables

I have four tables.
Person(
GUID uniqueidentifier
LastName varchar(20)
FirstName varchar(20)
SSN varchar(20)
ResidenceAddressGUID uniqueidentifier
)
Adress(
GUID uniqueidentifier
Street varchar(50)
Zip varchar(10)
)
Code(
CodeNumber
PersonGUID
Street
Zip
)
Tmp(
FirstName
LastName
Street
Zip
CodeNumber
)
And I want to move the data from Tmp to Person and Adress. What is the simplest way to do it?
EDIT:
I actually found out that TMP has a field "Code" that should be copied to the Code table with the street-adress and zip, no relationship to the address table.
No, you can't insert into multiple tables in one MySQL command. You can however use transactions.
BEGIN
INSERT INTO PERSON(LastName, FirstName)
SELECT
FirstName,
LastName
FROM TMP
INSERT INTO ADDRESS(Street)
SELECT
Street
FROM TMP;
COMMIT;
You can use a INSERT INTO statement combined with a SELECT statement to map the columns from TMP you want to insert into ADDRESS.
INSERT INTO Address(Street, Zip)
SELECT
Street,
Zip
FROM TMP
Also, you do the same thing for PERSON table.
INSERT INTO Person(LastName, FirstName, ResidenceAddressGUID)
SELECT
T.Street,
T.Zip,
A.GUID
FROM TMP T INNER JOIN ADDRESS A
ON T.Street = A.Street
AND T.Zip = A.Zip
Based on your later comments, I modified my queries and I hope now you understand the pattern and can do the queries for the CODE table yourself.
If (Address&Zip) combination is unique, you could use this:
INSERT INTO Address
SELECT DISTINCT
T.Street,
T.Zip
FROM
TMP T LEFT JOIN
Address A ON A.Zip = T.Zip AND Z.Street = T.Street
WHERE
A.GUID IS NULL
INSERT INTO Person (
FirstName,
LastName,
ResidenceAddressGUID)
SELECT
T.FirstName,
T.LastName,
A.GUID
FROM
TMP T INNER JOIN
Address A ON A.Street = T.Street AND A.ZIP = T.ZIP
If they are not unique, you should have a look at mssql INSERT OUTPUT option
Select statements can be used in combination with an insert statement to copy data from one table to another. One caveat, you must include a primary key for the tmp data your moving. In my example, I have included a sequence, which would work with an Oracle database. Depending on how the keys are assigned you may be able to omit the sequence, such as when a MySql autonumber exists.
insert into Person(GUID, FirstName, LastName)
select PERSON_SEQ.nextval, FirstName, LastName from Tmp;
insert into Adress(GUID, Street, Zip)
select ADRESS_SEQ.nextval, Street,Zip from Tmp;

Best way to get multiple newly created key values from table inserts using SQL Server?

The function Scope_Identity() will provide the last generated primary key value from a table insert. Is there any generally accepted way to get multiple keys from an insertion of a set (an insert resulting from a select query)?
In SQL Server 2005 onwards, you can use the OUTPUT clause to get a returned set of values. From the linked article:
The following example creates the
EmployeeSales table and then inserts
several rows into it using an INSERT
statement with a SELECT statement to
retrieve data from source tables. The
EmployeeSales table contains an
identity column (EmployeeID) and a
computed column (ProjectedSales).
Because these values are generated by
the SQL Server Database Engine during
the insert operation, neither of these
columns can be defined in #MyTableVar.
USE AdventureWorks ;
GO
IF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL
DROP TABLE dbo.EmployeeSales;
GO
CREATE TABLE dbo.EmployeeSales
( EmployeeID int IDENTITY (1,5)NOT NULL,
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL,
ProjectedSales AS CurrentSales * 1.10
);
GO
DECLARE #MyTableVar table(
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL
);
INSERT INTO dbo.EmployeeSales (LastName, FirstName, CurrentSales)
OUTPUT INSERTED.LastName,
INSERTED.FirstName,
INSERTED.CurrentSales
INTO #MyTableVar
SELECT c.LastName, c.FirstName, sp.SalesYTD
FROM HumanResources.Employee AS e
INNER JOIN Sales.SalesPerson AS sp
ON e.EmployeeID = sp.SalesPersonID
INNER JOIN Person.Contact AS c
ON e.ContactID = c.ContactID
WHERE e.EmployeeID LIKE '2%'
ORDER BY c.LastName, c.FirstName;
SELECT LastName, FirstName, CurrentSales
FROM #MyTableVar;
GO
SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM dbo.EmployeeSales;
GO
Use the row count and last identity value....
DECLARE #LastID int
DECLARE #Rows int
--your insert from a select here
SELECT #LastID=##IDENTITY, #Rows=##ROWCOUNT
--set of rows you want...
SELECT * FROM YourTable Where TableID>#LastID-#Rows AND TableID<=#LastID

Resources