While inserting data to two tables using stored procedure I am getting a mismatch error - sql

I have a table called CompanyMaster_tbl with a table structure as follows.
Cid CompanyName Deleted
and another table named DepartmentMaster_tbl,with a table structure as follows.
dtld dtname dtphone dtemail cid deleted
I've written a stored procedure for inserting data into these tables as follows.
CREATE PROCEDURE [dbo].[InsertDetails](
#companyName varchar(150),
#dname varchar(150),
#dphon varchar(150),
#deleted int,
#cid int OUTPUT
) AS
BEGIN
INSERT INTO [dbo].CompanyMaster_tbl
VALUES (#companyName)
select #cid=cid
from [dbo].CompanyMaster_tbl
WHERE ##ROWCOUNT > 0 AND cid = scope_identity()
insert into DepartmentMaster_tbl
values(#dname,
#dphon)
end
When I execute this SP, i am getting error like this:
Column name or number of supplied values does not match table definition.

try this , mention coloumn name
INSERT INTO [dbo].CompanyMaster_tbl (CompanyName )
VALUES (#companyName)
INSERT into DepartmentMaster_tbl (dname,dphon)
values(#dname, #dphon)

You are giving wrong number of values to the table i.e. you have two columns in table CompanyMaster_tbl(i think your cid is identity(auto generated) there fore i did not mention it) but you can give only one value to the table, and same thing applies for DepartmentMaster_tbl. if you can't give the values to the table then mention column names in the insert statement otherwise give all column value
e.g.
Insert into CompanyMaster_tbl(CompanyName) values(#companyName)
or
Insert into CompanyMaster_tbl values(#companyName, #deleted)

Related

Why is this temporary table throwing an error about the number of column supplied?

I'm trying to run this specific code for a temp table, but somehow I get this error
Column name or number of supplied values does not match table definition
What's wrong?
DROP TABLE IF EXISTS #GamesDistribution
CREATE TABLE #GamesDistribution
(
Platform nvarchar(255),
Name nvarchar(255),
NA_Sales numeric,
EU_Sales numeric,
JP_Sales numeric
)
INSERT INTO #GamesDistribution
SELECT
properties.Platform,
properties.Name,
revenue.NA_Sales,
revenue.EU_Sales,
revenue.JP_Sales
FROM
games_properties AS Properties
JOIN
games_revenue AS Revenue ON properties.Game_ID = Revenue.Game_ID
--GROUP BY properties.platform
--ORDER BY Total_Games DESC, Total_NA_Sales DESC, Total_EU_Sales DESC, Total_JP_Sales DESC;
The problem here is that prior to you running your batch the table already exists. As such when the batch is parsed, by the compiler, the compilation fails; because the number of columns doesn't match that of the table already exists.
This can be replicated with the following:
CREATE TABLE #t (I int);
INSERT INTO #t (I)
VALUES(1);
GO
DROP TABLE IF EXISTS #t;
CREATE TABLE #t (I int, D date);
INSERT INTO #t
VALUES(2,GETDATE());
GO
SELECT *
FROM #t;
GO
DROP TABLE #t
db<>fiddle
This returns the error:
Msg 213, Level 16, State 1, Line 10
Column name or number of supplied values does not match table definition.
And the dataset:
I
1
This is because the 2nd batch, with the DROP TABLE IF EXISTS never ran; the compilation failed.
The "simple" solution here would be to put your DROP IF EXISTS in a separate batch, and also specify your columns:
DROP TABLE IF EXISTS #GamesDistribution;
GO
CREATE TABLE #GamesDistribution (Platform nvarchar(255),
Name nvarchar(255),
NA_Sales numeric, --Where is your precision and scale?
EU_Sales numeric, --Where is your precision and scale?
JP_Sales numeric); --Where is your precision and scale?
INSERT INTO #GamesDistribution (Platform,Name, NA_Sales,EU_Sales,JP_Sales)
SELECT properties.Platform,
properties.Name,
revenue.NA_Sales,
revenue.EU_Sales,
revenue.JP_Sales
FROM dbo.games_properties AS Properties
JOIN dbo.games_revenue AS Revenue ON properties.Game_ID = Revenue.Game_ID;
You can actually do this way
DROP TABLE IF EXISTS #GamesDistribution
SELECT properties.Platform,
properties.Name,
revenue.NA_Sales,
revenue.EU_Sales,
revenue.JP_Sales
INTO #GamesDistribution
FROM games_properties AS Properties
JOIN games_revenue AS Revenue
ON properties.Game_ID = Revenue.Game_ID
and then you can check the columns' data types of the temp table:
EXEC tempdb..sp_help '#GamesDistribution'
SELECT *
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID('tempdb..#GamesDistribution');
Note: It's always better to ensure the columns' data types. Your query might list different columns' data types.
Add GO statement under drop table as below.
DROP TABLE IF EXISTS #GamesDistribution
GO
CREATE TABLE #GamesDistribution
(
.
.
.

Create a procedure to insert multiple values into a table, using a single variable

Goal: To create a procedure to insert multiple values into a table, using a single variable.
Challenge: Instead of making multiple hits in the same table, I have created a single variable (#SQL) and stored multiple columns (fm_id and shdl_id ) results in it but I am unable to use this single variable in the insert statement.
Code:
create proc abc
(
#org_id numeric(10,0),
#shdl_id numeric(10,0),
#usr_id numeric(10,0),
#tst_id numeric(10,0)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL NUMERIC(10);
SET #SQL= (SELECT fm_id,#shdl_id FROM [dbo].[students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id)
INSERT INTO [USER]
SELECT org_id,#usr_id,TST_ID,login_name,#SQL FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
END
GO
Error :
Msg 213, Level 16, State 1, Procedure abc, Line 14 [Batch Start Line
94] Column name or number of supplied values does not match table
definition.
First you need to make your SELECT return only one value into the variable. There's no point selecting #shdl_id because you already know it?
DECLARE #pFMID NUMERIC(10);
SELECT #pFMID = MAX(fm_id) FROM [dbo].[students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id);
Then because you're not inserting a value into every column in the user table you need to explicitly state which columns to fill. Replace x1..x5 below with real column names (in the order the SELECT has them)
INSERT INTO [USER](x1,x2,x3,x4,x5)
-- ^^^^^^^^^^^^^^^
-- REPLACE THESE WITH REAL NAME
SELECT org_id,#usr_id,TST_ID,login_name,#pFMID FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
END
GO
And as Uueerdo pointed out, this first query is a bit of a waste of time, we can write this:
create proc abc
(
...
)
AS
BEGIN
INSERT INTO [USER](x1,x2,x3,x4,x5)
SELECT org_id,#usr_id,TST_ID,login_name,fm_id FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
-- ^^^^^
-- look!
You can only get away with leaving the column list off an INSERT if you're inserting the same number of columns the table has:
CREATE TABLE x(col1 INT, col2 INT);
INSERT INTO x VALUES (1,2) -- works
INSERT INTO x VALUES (1) -- fails: which column should have the 1?
INSERT INTO x(col1) VALUES (1) -- works: col1 shall have the 1

Select row just inserted without using IDENTITY column in SQL Server 2012

I have a bigint PK column which is NOT an identity column, because I create the number in a function using different numbers. Anyway, I am trying to save this bigint number in a parameter #InvID, then use this parameter later in the procedure.
ScopeIdentity() is not working for me, it saved Null to #InvID, I think because the column is not an identity column. Is there anyway to select the record that was just inserted by the procedure without adding an extra ID column to the table?
It would save me a lot of effort and work if there is a direct way to select this record and not adding an id column.
insert into Lab_Invoice(iID, iDate, iTotal, iIsPaid, iSource, iCreator, iShiftID, iBalanceAfter, iFileNo, iType)
values (dbo.Get_RI_ID('True'), GETDATE(),
(select FilePrice from LabSettings), 'False', #source, #user, #shiftID, #b, #fid, 'Open File Invoice');
set #invID = CAST(scope_identity() AS bigint);
P.S. dbo.Get_RI_ID('True') a function returns a bigint.
Why don't you use?
set #invId=dbo.Get_RI_ID('True');
insert into Lab_Invoice(iID,iDate,iTotal,iIsPaid,iSource,iCreator,iShiftID,iBalanceAfter,iFileNo,iType)
values(#invId,GETDATE(),(select FilePrice from LabSettings),'False',#source,#user,#shiftID,#b,#fid,'Open File Invoice');
You already know that big id value. Get it before your insert statement then use it later.
one way to get inserted statement value..it is not clear which value you are trying to get,so created some example with dummy data
create table #test
(
id int
)
declare #id table
(
id int
)
insert into #test
output inserted.id into #id
select 1
select #invID=id from #id

Confusion about Stored Procedure

I have written a stored procedure for inserting data into my table. These are my table's columns with their datatype:
Ad nvarchar(150),
Yazar nvarchar(150),
SayfaSayisi smallint,
KategoriId int
Gmc datetime,
HostName nvarchar(150)
The problem is that Gmc and HostName have their own default values. So I can't use these two in the stored procedure.
Gmc ---> GetDate() (to get insert date)
HostName --> Host_Name( )
So when I execute the query I am getting this error.
There are more columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES clause must match the number of columns specified in the INSERT statement
This is the query
Create proc Kitap_Insert
#Ad nvarchar(150),
#Yazar nvarchar(150),
#SayfaSayisi smallint,
#KategoriId int
Gmc datetime,
HostName nvarchar(150)
as
Insert into Kitap(Id, Ad, Yazar, SayfaSayisi, KategoriId)
values(#Ad, #Yazar, #SayfaSayisi, #KategoriId)
What is the proper way of doing this?
You need remove ID from insert list
Insert into Kitap(Ad,Yazar,SayfaSayisi,KategoriId)
values(#Ad,#Yazar,#SayfaSayisi,#KategoriId)
or add a value for it as below
Insert into Kitap(Id,Ad,Yazar,SayfaSayisi,KategoriId)
values(#ID, #Ad,#Yazar,#SayfaSayisi,#KategoriId)
Instead of :
Insert into Kitap(Id,Ad,Yazar,SayfaSayisi,KategoriId)
values(#Ad,#Yazar,#SayfaSayisi,#KategoriId)
Use:
INSERT INTO Kitap(Ad,Yazar,SayfaSayisi,KategoriId)
VALUES (#Ad,#Yazar,#SayfaSayisi,#KategoriId)
You are asking SQL engine that you will provide id (an additional field) as well (field that doesn't exist in the table or is an auto increment field) and you are not providing the value for the same and hence your error here are more columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES clause must match the number of columns specified in the INSERT statement
So remove additional Id from your insert query.
The error you are getting because you tried to insert value into more column names than specified in Values Clause.
If you have ID column as Auto-increment field in table so you dont have to include that ID column in so your insert query will be like this:-
Insert into Kitap
(Ad,Yazar,SayfaSayisi,KategoriId)
values
(#Ad,#Yazar,#SayfaSayisi,#KategoriId)
If you don't have ID column as Auto-increment field in table so you provide value to that id column also in Value Clause so your insert query will be like this:-
NOTE:-
You have to calculate and Set Value to #Id variable before using it in Insert Query
Declare #Id as INT
SET #ID = ---- set here with some value which will become Primary key(I think)
Insert into Kitap
(Id,Ad,Yazar,SayfaSayisi,KategoriId)
values
(#Id, #Ad,#Yazar,#SayfaSayisi,#KategoriId)

SQL Server 2012. Copy row into single column on another table

I am working with SQL Server on the AdventureWorks2012 Database. I am working with triggers. I would like to copy any new inserted row into one single column in another table called AuditTable. Basically whenever I insert into the parson.address table, I would like to copy all of the rows into the AuditTable.prevValue column. I know how to insert etc, I am not sure how to write to one column.
Here is the general idea.
USE [AdventureWorks2012]
ALTER TRIGGER [Person].[sPerson] ON [Person].[Address]
FOR INSERT AS INSERT INTO AdventureWorks2012.HumanResources.AuditTable(PrevValue) select
AddressID,AddressLine1,AddressLine2,City, StateProvinceID, PostalCode, SpatialLocation, rowguid, ModifiedDate FROM Inserted
ERROR: The select list for the INSERT statement contains more items than the insert list. The number of SELECT values must match the number of INSERT columns.
Thank you for any assistance. I have searched loads but cannot find the exact solution anywhere.
The error message says it all - you can't insert 9 columns of different types into a single column. Assuming that your destination AuditTable.PrevValue column is NVARCHAR(), you could flatten your insert as follows, by concatenating the columns and casting non-char columns to n*char:
INSERT INTO AdventureWorks2012.HumanResources.AuditTable(PrevValue)
SELECT
N'ID : ' + CAST(AddressID AS NVARCHAR(20)) + N'Address: ' + AddressLine1 +
N', ' +AddressLine2 + ....
FROM Inserted
IMO keeping one long string like this makes the Audit table difficult to search, so you might consider adding SourceTable and possibly Source PK columns.
You could also consider converting your row to Xml and storing it as an Xml column, like this:
create table Audit
(
AuditXml xml
);
alter trigger [Person].[sPerson] ON [Person].[Address] for INSERT AS
begin
DECLARE #xml XML;
SET #xml =
(
SELECT *
FROM INSERTED
FOR XML PATH('Inserted')
);
insert into [MyAuditTable](AuditXml) VALUES (#xml);
end