Stored Procedure as Parameter in MERGE [INSERT] Statement - sql

I need to merge two tables in following way:
Target has one extra Column ID. This Id is coming FROM another Single Column Master Table.
While Inserting the Record in Merge Statement I need to INSERT a new row into mater table and use its id to insert into TARGET table.
I have created a Stored Procedure that Inserts and returns newly inserted ID. Now the Problem is inside SQL Merge, we can't call a stored Proc.
What could be the solution of this issue? Cant use Scalar functions as INSERT can't be performed in Functions.
DECLARE #temp INT
MERGE dbo.mytabletarget T
USING dbo.mytableSource S
ON T.refId=S.RefId
WHEN MATCHED THEN
UPDATE
SET T.col1=S.col1,
T.Col2=S.Col2
WHEN NOT MATCHED BY TARGET THEN
INSERT (Id,col1,col2)
VALUES({Here i need value from SP. SP simply Inserts a new Id into master table and Returns it},S.col1,S.col2);
GO

What could be the solution of this issue?
Do not use a stored procedure. Obvious, isn't it?
For a merge statement, you pretty much are stuck with doing the commands right there in the statement. Merge focuses on ETL loads and has advantages as well as limitations.
Basically, put the logic into the merge statement.
While Inserting the Record in Merge Statement I need to INSERT a new row into mater table
and use its id to insert into TARGET table.
Hm, lookup table maintenance?
The regular approach for that is ti make sure the lookup table is filled first (in a separate statement). ETL (and that is where merge comes from) often works along stages for that particular reason.
Sorry, I do not have a better solution either ;(

Related

Insert or Update user-defined table type in a stored procedure

I'm currently working on a project where I insert or update a lot of data frequently to a remote database. The data volume is around 50 sets of data with 500-800 rows each, that goes into the same table.
Currently I have a stored procedure that I call for every row to insert or update (simplified for easier read):
ALTER PROCEDURE stat_memberstat_upsert
...
AS
BEGIN
UPDATE Memberstats ...
if(##ROWCOUNT = 0)
BEGIN
INSERT INTO Memberstats ...
END
END
This works, but as you can see it mounts to a lot of calls to the same stored procedure (worst case around 100,000 calls). I'm looking into User-defined table type, which sound like a good solution, because it decreases the calls to the database server, with a more bulk like structure. The problem is that when I look at the solutions, tutorials and documentations I find that no one mentions a way to do a insert/update routine with the table type; it's either insert or update.
Is there a way, when working with table types, to do a insert/update call?
Alternatively I have thought about two workaround solutions:
1: Using cursor
I could use a cursor to iterate through the table type value and call the stat_memberstat_upsert procedure above for each row. This will not prevent the many calls to the procedure, but since the calls are done from a local stored procedure the speed might increase.
How to do ForEach on user defined table type in SQL Server stored procedure? (answer "Why not use a cursor ???")
2: Pre validate data
Second solution is to retrieve the already inserted rows primary keys, validate them against the incoming data and sort them into 2 tables, where one is for inserts and the other one is for updates. Then execute both tables to the database. This means that I need to encapsulate this in a transaction so the table will not change during the time is take to validate and execute the insert and update.
Would any of these be a good solution?
Both the solution might slow down further.
You can simply have insert statements into a table
ALTER PROCEDURE stat_memberstat_upsert
...
AS
INSERT INTO Memberstats_temp ...
END
and have a batch process which will run at low traffic time to update/insert the Memberstats table from Memberstats_temp table after that truncating this temp table. This wouldn't be a solution if you need real time update to the table.

Reading values inserted by trigger in a different table

I'm having the following issue: I have a trigger on a table A, whose purpose is to compute some values and insert them in a completely different table B.
The problem is that, somewhere in that logic, there is a loop that requires the values that would have been freshly inserted into table B.
I've noticed that SQL Server executes all the INSERT commands at once, after exiting the trigger.
ALTER TRIGGER [dbo].[InsertTrade]
ON [dbo].[Blotter]
AFTER INSERT
AS
BEGIN
/* compute #Variables */
INSERT INTO [dbo].[CompletelyUnrelatedTableWithoutTriggersOnIt]
VALUES #Variables
Is there any way of COMMMIT-ing that INSERT and being able to read those values while still in the trigger?
Thanks,
D.
First of all, be very careful with how you are constructing your trigger. If you're using INSERT...VALUES() in a trigger, it's a good indication that you're assuming there will only ever be one record in the INSERTED table. Never make that assumption. Instead your logic should be INSERT...SELECT <computed cols> FROM INSERTED
Second, if you want to get out the values you just put in, you could use the OUTPUT clause but I'm not sure that's what you mean (it's not entirely clear what you want to do with the values) then you will have access to the final values that were inserted "while still in the trigger"
If that's not what you want, perhaps it would be better to encapsulate all this functionality into a proc.

Need a sql statement to do upate and insert at the same time

I need a sql statement, to insert a new row in one database table and update an existing row in another database table based on some conditions.
Is there a way to do this? To insert a row in one table and update a row in another database table in one sql statement?
Thanks in advance!
Yes, they are called Transactions, and are implemented with START TRANSACTION and COMMIT/ROLLBACK with something like:
START TRANSACTION;
INSERT INTO ...
UPDATE table2 SET name='TOTO' WHERE type=1;
COMMIT;
EDIT
This is not in fact one SQL query, but the operation is done atomically - and I think that is what you need.
A single SQL statement allows you to update one table, not several; if that statement is a MERGE then you can specify insert/update/delete actions but still targeting just the same one target table.
If you just want consistency, use transactions; until a transaction is committed, changes within it are not visible to the outside world.
If you want that a single update (which you cannot control) resulted in a coordinated insert, use an on update trigger in the table being updated. The trigger would insert appropriate row(s) into other table(s).
You can use Trigger to update second table on insert of first table
Yes, it's possible with stored procedures.
Watch this: Stored procedures

Debugging sub-queries in TSQL Stored Procedure

How do I debug a complex query with multiple nested sub-queries in SQL Server 2005?
I'm debugging a stored procedure and trigger in Visual Studio 2005. I'd like to be able to see what the results of these sub-queries are, as I feel that this is where the bug is coming from. An example query (slightly redacted) is below:
UPDATE
foo
SET
DateUpdated = ( SELECT TOP 1 inserted.DateUpdated FROM inserted )
...
FROM
tblEP ep
JOIN tblED ed ON ep.EnrollmentID = ed.EnrollmentID
WHERE
ProgramPhaseID = ( SELECT ...)
Visual Studio doesn't seem to offer a way for me to Watch the result of the sub query. Also, if I use a temporary table to store the results (temporary tables are used elsewhere also) I can't view the values stored in that table.
Is there anyway that I can add a watch or in some other way view these sub-queries? I would love it if there was some way to "Step Into" the query itself, but I imagine that wouldn't be possible.
Ok first I would be leary of using subqueries in a trigger. Triggers should be as fast as possible, so get rid of any correlated subqueries which might run row by row instead of in a set-based fashion. Rewrite to joins. If you only want to update records based on what was in the inserted table, then join to it. Also join to the table you are updating. Exactly what are you trying to accomplish with this trigger? It might be easier to give advice if we understood the business rule you are trying to implement.
To debug a trigger this is what I do.
I write a script to:
Do the actual insert to the table
without the trigger on on it
Create a temp table named #inserted
(and/or one named #deleted)
Populate the table as I would expect
the inserted table in the trigger to
be populated from the insert you do.
Add the trigger code (minus the
create or alter trigger parts)
substituting #inserted every time I
reference inserted. (if you plan to
run multiple times until you are
ready to use it in a trigger throw
it in an explicit transaction and
rollback after checking your
results.
Add a query to check the table(s)
you are changing with the trigger for
the values you wanted to change.
Now if you need to add debug
statements to see what is happening
between steps, you can do so.
Run making changes until you get the
results you want.
Once you have the query working as
you expect it to, it is easy to take
the # signs off inserted and use it
to create the body of the trigger.
This is what I usually do in this type of scenerio:
Print out the exact sqls getting generated by each subquery
Then run each of then in the Management Studio as suggested above.
You should check if different parts are giving you the right data you expect.

update table without using update statement

can anyone tell that how to update some records of a table without using update statement. it is possible using select statement.
I don't think you can update the table without update statement.
It is not possible with a select statement.
You can delete a row and insert the same row + your changes which is in many ways like an update, but will cause lots of trouble with foreign keys.
Oh, and your DBA might kill you.
You can use
REPLACE INTO tablename(primary key, ...{rest of the columns in the table})
VALUES(the same primary key, new values );
This will delete the previous row and insert a new row with the same primary key and updated column values. Not so much worthwhile, but maybe there is some other way.
It depends what tools you are using and what you actually want to achieve.
There are libraries which allow you to update data you got from a select statement. (eg. ORM's like NHibernate, I think ADO.NET also). These libraries are writing the update statements for you
You can use functions or triggers which change data when you just perform a select statement. In these functions or trigger, you still have an update statement.
For security reasons, you have to make sure that nobody injects an update statement into your select statement. So it is not just save to only perform a select statement.
how to update some records of a table
without using update statement.
Use a MERGE statement.
it is possible using select statement.
Logically, an update is a delete and an insert: INSERT INTO..SELECT to a staging table, modifying the data as appropriate, then DELETE then INSERT INTO..SELECT from staging table.
On the off chance you were asking how this happened when a module ran a select statement it created, then you need to read up on SQL injection. You cannot do an update without an update statment of some kind (includiing not only update but doing delete and then insert or useiing merge) and the user must have update permission on a table, but you can add an update to a select statement that is dymanically created if you haven't correctly parametized it to avoid SQL injection.