Stored procedure doesn't insert data into one of the table even though data looks good - sql

I'm trying to insert data into two tables [Product]., it's inserting into one of the tables not inserting `[Product]. It returns an empty table. Not sure how to handle multiple inserts in the stored procedure:

Try this
INSERT INTO [Product].[LKStandardProductGroup]
([StandardProductGroupID],[StandardProductID])
SELECT
#StandardProductGroupID as [StandardProductGroupID] ,
value as [StandardProductID]
FROM STRING_SPLIT(#StandardProductCodes,',') inp
INNER JOIN [Product].[StandardProduct] sp WITH(NOLOCK)
ON sp.[StandardProductID] = inp.value

Related

SQL check if record exists in table before bulk insert

I currently have a stored procedure that performs bulk insert into a table named "TomorrowPatients" from a .csv file. When performing the bulk insert, I need to determine if the record being added already exists within the table and if so DO NOT add the record. If the record does not exist then I need to APPEND it to the table. What is the most efficient way to go about this? Any help will be greatly appreciated.
EDIT: I have created a temp table called "TomorrowPatients_Temp". I am trying to use this table to determine which records to insert.
Insert your the whole data into a temporary table, say #TempData.Then use the following code :
INSERT INTO TommorowPatients
SELECT * FROM #TempTable TT
LEFT JOIN TommorowPatients TP ON TT.PatientId = TP.PatienId
AND TT.PatientName = TP.PatientName
AND TT.PatientSSN = TP.PatientSSN
WHERE TP.PatientId IS NULL
Where PatientId is you primary key for the TommorowPatients table.
DO NOT add the "RoomNumber" column with the LEFT JOIN like : TT.RoomNo = TP.RoomNo. This way even if the room number changes, new data won't be inserted as we have joined only based on patient specific data.

How to get list of deleted records in SQL

My goal is to separate two types of data in table that is being sent to a stored procedure. In this table, I will have two kinds of records of type 1 and type 2, let's say.
I want to delete all data of type 2 from the inputted table but still have it stored in a separate temp table.
I know how to delete data with the following statement:
DELETE t
FROM #tags t
WHERE t.Type = 2
Is there a way to retrieve the deleted records so I can insert them into a separate temp table?
Otherwise I will have to have a separate code block before that looks like the following:
INSERT #dynamicTags(String)
SELECT String
FROM #tags t
WHERE t.Type = 2
Any ideas to combine the two above statements into one?
If using SQL Server you can do this with the OUTPUT clause:
DELETE t
FROM #tags t
OUTPUT DELETED.* INTO #MyTableVar
WHERE t.Type = 2
If you are using postgres you can use the returning clause:
http://www.postgresql.org/docs/9.3/static/sql-delete.html

The multi-part identifier "##ABMPARENT.SYM_INDEX" could not be bound

I'm running the code below in SQL server 2012 and am getting an error msg saying that
"The multi-part identifier "##ABMPARENT.SYM_INDEX" could not be bound."
I've looked through several over related threads which usually result in someone having spelt the table name incorrectly, used the where clause more than once in a single select statement etc ... However I've used the intellisense and have referenced the correct column / table as far as I can see.
Can anybody tell what is causing the error?
Thanks
Ps. I don't have access to save a SQL view which is why I'm using temp tables for this.
IF OBJECT_ID('tempdb..#ABMPARENT') IS NOT NULL
DROP TABLE ##ABMPARENT
IF OBJECT_ID('tempdb..#ALLSYMBOLS') IS NOT NULL
DROP TABLE ##ALLSYMBOLS
SELECT dbo.KLX_PARENT_CHILD.PARENT_NAME ,
dbo.KLX_MASTER_SYMBOL.SYM_INDEX ,
dbo.KLX_MASTER_SYMBOL.SYM_NAME ,
dbo.KLX_SYM_DESC.DESCRIPTION
INTO ##ABMPARENT
FROM dbo.KLX_PARENT_CHILD
INNER JOIN dbo.KLX_MASTER_SYMBOL ON dbo.KLX_PARENT_CHILD.SYM_INDEX = dbo.KLX_MASTER_SYMBOL.SYM_INDEX
INNER JOIN dbo.KLX_SYM_DESC ON dbo.KLX_MASTER_SYMBOL.SYM_INDEX = dbo.KLX_SYM_DESC.MICRO_OBJ_ID
WHERE ( dbo.KLX_PARENT_CHILD.PARENT_NAME = 'ABMRCTREE_1314' )
AND ( dbo.KLX_MASTER_SYMBOL.SYM_NAME LIKE 'LVRC%' )
SELECT dbo.KLX_PARENT_CHILD.PARENT_NAME ,
dbo.KLX_MASTER_SYMBOL.SYM_INDEX ,
dbo.KLX_MASTER_SYMBOL.SYM_NAME ,
dbo.KLX_SYM_DESC.DESCRIPTION ,
dbo.KLX_PARENT_CHILD.PARENT_INDEX
INTO ##ALLSYMBOLS
FROM dbo.KLX_PARENT_CHILD
INNER JOIN dbo.KLX_MASTER_SYMBOL ON dbo.KLX_PARENT_CHILD.SYM_INDEX = dbo.KLX_MASTER_SYMBOL.SYM_INDEX
INNER JOIN dbo.KLX_SYM_DESC ON dbo.KLX_MASTER_SYMBOL.SYM_INDEX = dbo.KLX_SYM_DESC.MICRO_OBJ_ID
SELECT *
FROM ##ALLSYMBOLS
where [##ABMPARENT].SYM_INDEX = ##ALLSYMBOLS.PARENT_INDEX
Your statement SELECT * FROM ##ALLSYMBOLS where [##ABMPARENT].SYM_INDEX = ##ALLSYMBOLS.PARENT_INDEX does not reference a table named [##ABMPARENT], so you cannot reference a column of that table. Did you intend to do a join in that query?
What #Gabe said. Your last select statment is referencing a table that is not in the from clause.
Nothing wrong with temp tables, but why are you using global temp tables (##some-table-name) instead of local temp tables (#some-table-name). Global temp tables are visible to every session, and are, in my experience, a code smell.
Local temp tables are scoped to to your session (or if created within a stored procedure, to a single stored procedure exection. Local temp tables are dropped when the stored procedure that created exits or when the session is closed, whichever comes first. Further, local temp table tables, once created in a stored procedure are visible to nested stored procedures -- e.g., stored procedure A creates temp table #WORK and then invokes stored procedure B which in turn invokes stored procedure C. The temp table #WORK is usable and visible to both stored procedures B and C.
It complicates stored procedure creation though. A stored procedure referencing a temp table that it doesn't create can't be created unless that temp table exists for the connection at the time create procedure is executed, so you need to do something like:
create table #foo ( ... )
go
create proc dbo.A as ...
go
drop table #foo
go
And a code suggestion: use correlation names for your tables, like so:
select *
from dbo.Foo t1
join dbo.Bar t2 on t2.id = t1.bar_id
Your SQL will be way more readable and, you only have to type the long convoluted table name once. You, your coworkers and the physical therapist you've been seeing for repetitive stress syndrome will appreciate it.

Insert Multiple Rows into Table from a Table

I have a SQL Server 2008 database. The database has a stored procedure which receives two strings as parameters. One parameter is used to build a temp table which will usually only have 1 or 2 rows but theoretically could have more.
For each row in the temp table, I need to insert a row into a different table that consists of the other parameter and the contents of the temp table. Is there a way to do this without a cursor?
I've tried variations on the following:
Pseudo code:
procedure InsertLinks(#Key varchar(36), #LinkKey varchar(36)
tempLinks Table = getLinks(#LinkKey)
Insert into MyTable (Key, LinksTo) Values (#Key, Select LinksTo From tempLinks)
The VALUES clause is messed up - you have a single value comma a table. That's not valid.
The following should work just fine:
INSERT INTO MyTable (Key, LinksTo)
SELECT #Key, LinksTo
FROM tempLinks

How to fix this stored procedure problem

I have 2 tables. The following are just a stripped down version of these tables.
TableA
Id <pk> incrementing
Name varchar(50)
TableB
TableAId <pk> non incrementing
Name varchar(50)
Now these tables have a relationship to each other.
Scenario
User 1 comes to my site and does some actions(in this case adds rows to Table A). So I use a SqlBulkCopy all this data in Table A.
However I need to add the data also to Table B but I don't know the newly created Id's from Table A as SQLBulkCopy won't return these.
So I am thinking of having a stored procedure that finds all the id's that don't exist in Table B and then insert them in.
INSERT INTO TableB (TableAId , Name)
SELECT Id,Name FROM TableA as tableA
WHERE not exists( ...)
However this comes with a problem. A user at any time can delete something from TableB so if a user deletes say a row and then another user comes around or even the same user comes around and does something to Table A my stored procedure will bring back that deleted row in Table B. Since it will still exist in Table A but not Table B and thus satisfy the stored procedure condition.
So is there a better way of dealing with two tables that need to be updated when using bulk insert?
SQLBulkCopy complicates this so I'd consider using a staging table and an OUTPUT clause
Example, in a mixture of client pseudo code and SQL
create SQLConnection
Create #temptable
Bulkcopy to #temptable
Call proc on same SQLConnection
proc:
INSERT tableA (..)
OUTPUT INSERTED.key, .. INTO TableB
SELECT .. FROM #temptable
close connection
Notes:
temptable will be local to the connection and be isolated
the writes to A and B will be atomic
overlapping or later writes don't care about what happens later to A and B
emphasising the last point, A and B will only ever be populated from the set of rows in #temptable
Alternative:
Add another column to A and B called sessionid and use that to identify row batches.
One option would be to use SQL Servers output clause:
INSERT YourTable (name)
OUTPUT INSERTED.*
VALUES ('NewName')
This will return the id, name of the inserted rows to the client, so you can use them in the insert operation for the second table.
Just as an alternative solution you could use database triggers to update the second table.