I tried to make a stored procedure the insert data to a table:
create procedure AddEmployee
(
#FirstName nvarchar(20)
, #LastName nvarchar(20)
, #BirthDate datetime
, #Country nvarchar(15)
, #City nvarchar(15)
)
as
insert into Employees
values (#FirstName, #LastName, #BirthDate, #Country, #City)
go
But when I run it I get the error message:
Msg 213, Level 16, State 1, Procedure AddEmployee, Line 2 [Batch Start Line 17]
Column name or number of supplied values does not match table definition.
I looked at this question but it didn't solve my problem:
Create a stored procedure to insert new data into a table
When using insert, always include the columns names:
create procedure AddEmployee (
#FirstName nvarchar(20) ,
#LastName nvarchar(20) ,
#BirthDate datetime,
#Country nvarchar(15),
#City nvarchar(15)
) as
begin
insert into Employees (FirstName, LastName, BirthDate, Country, City)
values (#FirstName, #LastName, #BirthDate, #Country, #City);
end;
Although SQL allows you to leave out the column names, you should include them as a best-practice. This is particularly important for those learning the language, so they learn the safer way to do things.
Related
in my database, there is a Stored Procedure with INSERT INTO statement. The problem is I want this stored procedure will return the StudentCode default value, I think it's impossible to use the SELECT TOP 1 statement to get this value because there may be multiple rows inserted at the same time. Any help or suggestions?. Thanks very much
ALTER PROC [dbo].[AddStudent]
#StudentName NVARCHAR(255),
#DoB DATETIME,
#Parent NVARCHAR(255),
#ParentContact VARCHAR(16),
#Address NVARCHAR(255),
#Class VARCHAR(6),
AS
INSERT INTO dbo.Student
( StudentCode , --I set default this column
StudentName,
DateOfBirth
NameParrent ,
PhoneContact ,
AddressParent ,
Class ,
)
VALUES ( DEFAULT , --StudentCode varchar(5)
#StudentName, --StudentName nvarchar(255)
#DoB, --DateOfBirth datetime
#Parent, --NameParrent nvarchar(255)
#ParentContact, --PhoneContact varchar(16)
#Address, --AddressParent nvarchar(255)
#Class --Class varchar(6)
)
-- How to return StudentCode field
Use OUTPUT INSERTED clause, as explained into official docs:-
INSERTED
Is a column prefix that specifies the value added by the
insert or update operation. Columns prefixed with INSERTED reflect the
value after the UPDATE, INSERT, or MERGE statement is completed but
before triggers are executed.
so your code is going to be like this:- (is not tested, but it guides you to accurate code)
ALTER PROC [dbo].[AddStudent]
#StudentName NVARCHAR(255),
#DoB DATETIME,
#Parent NVARCHAR(255),
#ParentContact VARCHAR(16),
#Address NVARCHAR(255),
#Class VARCHAR(6),
AS
DECLARE #StudentCodeInserted varchar(5)
INSERT INTO dbo.Student
( StudentCode, --I set default this column
StudentName,
DateOfBirth
NameParrent ,
PhoneContact ,
AddressParent ,
Class
)
OUTPUT inserted.StudentCode INTO #StudentCodeInserted
VALUES ( DEFAULT , --StudentCode varchar(5)
#StudentName, --StudentName nvarchar(255)
#DoB, --DateOfBirth datetime
#Parent, --NameParrent nvarchar(255)
#ParentContact, --PhoneContact varchar(16)
#Address, --AddressParent nvarchar(255)
#Class --Class varchar(6)
)
Select #StudentCodeInserted as StudentCodeInserted
You need to Return value after INSERT
DECLARE #generated_StudentCode table(StudentCode varchar(5))
INSERT INTO dbo.Student
( StudentCode, --I set default this column
StudentName,
DateOfBirth
NameParrent ,
PhoneContact ,
AddressParent ,
Class ,
)
OUTPUT inserted.StudentCode INTO #generated_keys
VALUES ( DEFAULT , --StudentCode varchar(5)
#StudentName, --StudentName nvarchar(255)
#DoB, --DateOfBirth datetime
#Parent, --NameParrent nvarchar(255)
#ParentContact, --PhoneContact varchar(16)
#Address, --AddressParent nvarchar(255)
#Class --Class varchar(6)
)
SELECT TOP 1 * FROM #generated_StudentCode
Read the following thread to have a better understanding
SQL Server - Return value after INSERT
May I ask a question regarding for the SQL Server stored procedure?
Basically I created a table called Customers and I want to write an INSERT statement inside of the stored procedure where I have been done using CURSOR.
When I execute my CREATE stored procedure should be fine and do not have any error message and also when I execute the stored procedure using EXECUTE statement without any data entry (7, Andy, Singapore) do not have any error message.
Lastly, when I put some data entry into the EXECUTE stored procedure and I got this error messages.
Msg 8146, Level 16, State 1, Procedure InsertCustomers_Cursor, Line 0 [Batch Start Line 40]
Procedure InsertCustomers_Cursor has no parameters and arguments were supplied.
Code:
create table customer
(
cust_id int primary key,
name varchar(100),
country varchar(50)
);
insert into customer
values (1, 'John Hammond', 'United States'),
(2, 'Mudassar Khan', 'India'),
(3, 'Robert Tan', 'Singapore'),
(4, 'Dennis Rodman', 'Indonesia'),
(5, 'Michelle Chia', 'Indonesia'),
(6, null, null);
select *
from customer;
CREATE PROCEDURE InsertCustomers_Cursor
AS
BEGIN
DECLARE #cust_id int,
#name varchar(100),
#country varchar(50)
DECLARE #Counter INT
SET #Counter = 1
DECLARE #AllRecords TABLE
(
cust_id int,
name varchar(100),
country varchar(50)
)
DECLARE InsertCustomers CURSOR READ_ONLY
FOR
SELECT cust_id, name, country
FROM customer
OPEN InsertCustomers
FETCH NEXT FROM InsertCustomers INTO #cust_id, #name, #country
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #AllRecords
VALUES (#cust_id, #name, #country)
FETCH NEXT FROM InsertCustomers INTO #cust_id, #name, #country
END
CLOSE InsertCustomers
DEALLOCATE InsertCustomers
END
GO
-- This EXEC statement cannot run the query
EXEC InsertCustomers_Cursor 7, 'Michael Labone', Indonesia
-- This EXEC statement can run the query and the results is to show how many are being affected
EXEC InsertCustomers
The issue is your SP doesn't expect any parameter and you are calling it passing parameters
EXEC InsertCustomers_Cursor 7, 'Michael Labone', Indonesia
To make it works properly, you need to create these parameters in the SP:
CREATE PROCEDURE InsertCustomers_Cursor
#cust_id int,
#name varchar(100),
#country varchar(50)
AS
BEGIN
...
And remove this part:
DECLARE #cust_id int,
#name varchar(100),
#country varchar(50)
There could be more elegant ways to declare these parameters but for the example I think it's enough.
I want to transfer data from source Database table named Patient (which contains many rows) to destination database tables(2) named Person & Patient.
I already have stored procedure named AddPatient in destination database which will add person related fields to Person table and other fields to Patient table, so I would like to execute that procedure and to assign the fields from source database as variables to it. The following are the code of AddPatient sp in destination database.
ALTER PROCEDURE [dbo].[AddPatient]
(
#TenantId BIGINT,
#FirstName NVARCHAR(100),
#LastName NVARCHAR(100),
#PersonNumber NVARCHAR(20),
#MobileNumber NVARCHAR(20),
#EmailId NVARCHAR(100),
#Address NVARCHAR(255),
#City NVARCHAR(50),
#ZipCode NVARCHAR(20),
#ListComments NVARCHAR(1000),
#Comment NVARCHAR(500),
#AlternateEmailId NVARCHAR(100) ,
#HomePhone NVARCHAR(20) ,
#Relative NVARCHAR(255) ,
#HasDiabetes [bit],
#HasBlooPressure [bit],
#AddedBy BIGINT,
#AddedDateTime smalldatetime,
#PersonId BIGINT OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
IF #TenantId IS NULL
RAISERROR('The value for #TenantID should not be null', 15, 1) -- with log
ELSE
BEGIN
DECLARE #new_person_id BIGINT
DECLARE #new_patient_id BIGINT
DECLARE #PatientIdentifier NVARCHAR(50)
EXEC dbo.GetNextPatientIdForTenant #TenantID, #PatientIdentifier OUTPUT
INSERT INTO dbo.Person
(
TenantId,
FirstName,
LastName,
PersonNumber,
MobileNumber,
EmailId,
Address,
City,
ZipCode,
AddedBy,
AddedDateTime
)
VALUES
(
#TenantId,
#FirstName,
#LastName,
#PersonNumber,
#MobileNumber,
#EmailId,
#Address,
#City,
#ZipCode,
#AddedBy,
#AddedDateTime
)
SELECT #new_person_id = SCOPE_IDENTITY()
INSERT INTO dbo.Patient
(
TenantId,
PatientIdentifier,
PersonId,
ListComments,
Comment,
AlternateEmailId,
HomePhone,
Relative,
HasDiabetes,
HasBlooPressure,
AddedBy,
AddedDateTime
)
VALUES
(
#TenantId,
#PatientIdentifier,
#new_person_id,
#ListComments ,
#Comment ,
#AlternateEmailId,
#HomePhone ,
#Relative ,
#HasDiabetes,
#HasBlooPressure,
#AddedBy ,
#AddedDateTime
)
SELECT #new_patient_id = SCOPE_IDENTITY()
SELECT #PersonId = #new_person_id
SELECT #new_patient_id
END
END
There is no TenantId & AddedBy field in source, so I want to assign both as 1 for all rows to be transfered.
I know Execute SQL Task will handles stored procedure and for each row data Foreach Loop Container will take care in SSIS. But I don't know how to assign the variables of sp in destination database to the fields of table from source database.
Anyone help me with this.
Thanks in advance !
I am trying to insert data into many tables in one SQL Server stored procedure. I am also using the identities from the tables that I have inserted data into to then resolve the many to many relationship by writing those identities to another table.
In theory the logic seems to be there for the stored procedure, but on execution only the first insert statement has been executed. Please could anyone assist with this.
The stored procedure is as follows:
Create Procedure [dbo].[InsertAllCustomerDetails]
(
--#CustomerID Bigint output,
#Firstname varchar(100),
#LastName varchar(100),
#Initials varchar(10),
#Title varchar(20),
#DateCreated datetime,
#isDeleted Bit,
--#ContactNumberID BIGINT Output,
#ContactNumber Varchar(100),
#ContactTypeID bigint,
#Street Varchar(550),
#AreaID BIGINT,
#isPreferred Bit
--#AddressID Bigint OutPut
)
AS
Insert Into Customer
(
FisrtName,
LastName,
Initials,
[Title],
DateCreated,
isDeleted
)
Values
(
#Firstname,
#LastName,
#Initials,
#Title,
#DateCreated,
#isDeleted
)
Declare #CustomerID BIGINT
SELECT #CustomerID = ##IDENTITY
RETURN #CustomerID
--This will now insert the contact details for the customer
Insert Into ContactNumber
(
ContactNumber,
ContactTypeID
)
Values
(
#ContactNumber,
#ContactTypeID
)
Declare #ContactNumberID BIGINT
SELECT #ContactNumberID = ##IDENTITY
--This will insert into the CustomerContactNumber
Insert Into CustomerContactNumber
(
ContactNumberID,
CustomerID
)
Values
(
#ContactNumberID,
#CustomerID
)
--This will insert the address
Insert Into [Address]
(
Street,
AreaID,
isPreferred
)
Values
(
#Street,
#AreaID,
#isPreferred
)
Declare #AddressID BIGINT
SELECT #AddressID = ##IDENTITY
--This will insert the relationship for the customer Address table
Insert into CustomerAddress
(
CustomerID,
AddressID
)
Values
(
#CustomerID,
#AddressID
)
I see two things:
You seem to have a typo in the Customer insert:
Insert Into Customer
(
FisrtName, <-- should be FirstName?
LastName,
You are RETURNing after the Customer insert - that's why only the first one runs
Declare #CustomerID BIGINT
SELECT #CustomerID = ##IDENTITY
RETURN #CustomerID <---- This exits the sproc
--This will now insert the contact details for the customer
Insert Into ContactNumber
I'm guessing the RETURN was there for debugging and not removed since it's obscured by the indentation.
I am looking for some advice how to optimize a couple of SQL stored procedures. With the 1st query I am doing insert, and with the 2nd one I am doing update, if the data exists.
What I want to do is merge both stored procedures in one, where the query will check if the data exists than update, else insert a new row.
Here is what I have at this time:
update SP:
ALTER PROCEDURE [dbo].[UpdateStep1](#UserId nvarchar(50), #First_Name nvarchar(50), #Last_Name nvarchar(50),
#TitlePosition nvarchar(30))
AS
BEGIN
UPDATE Company_Information
SET First_Name = #First_Name,
Last_Name = #Last_Name,
Title_Position=#TitlePosition,
WHERE UserId = #UserId
END
insert SP:
ALTER PROCEDURE [dbo].[InsertStep1](#UserId nvarchar(50), #First_Name nvarchar(50), #Last_Name nvarchar(50),
#TitlePosition nvarchar(30))
AS
BEGIN
INSERT INTO Company_Information(UserId,
First_Name,
Last_Name,
Title_Position)
VALUES
(#UserId,
#First_Name,
#Last_Name,
#TitlePosition)
END
So, I would like to merge both SP in one, and the SP to check if there is already data for that UserId than update, else insert a new row.
MERGE Statement?
CREATE PROCEDURE [dbo].[MERGEStep1](#UserId nvarchar(50), #First_Name nvarchar(50), #Last_Name nvarchar(50), #TitlePosition nvarchar(30))
AS
BEGIN
MERGE Company_Information WITH(HOLDLOCK) AS T
USING(SELECT 1 S) S
ON T.UserId = #UserId
WHEN MATCHED THEN UPDATE SET
First_Name = #First_Name,
Last_Name = #Last_Name,
Title_Position=#TitlePosition
WHEN NOT MATCHED THEN
INSERT (UserId, First_Name, Last_Name, Title_Position)
VALUES(#UserId, #First_Name,#Last_Name,#TitlePosition);
END
Follow these steps:
Create a variable to test it (ex: #id)
Select #id = UserId from Company_Information where UserId = #UserId
If #id = #userId update, otherwise insert
As #gbn specified, be aware of concurrence issues.