SQL Server Insert Into Select one row at a time - sql

I am trying to use
INSERT INTO [table]
SELECT [columns]
FROM [table2]
WHERE [clause]
It loads perfectly. There is an error on row (?) so the entire insert is rolled back. I am trying to get this to load before and after the error. Also found TRY...CATCH in SQL to handle these issues.
Now, CURSOR seems like the exact answer but everything I read states that CURSOR should be avoided and is not Best Practice.
Anyone have a better option for my exact situation.

Related

Using HoldLock Incorrectly in SQL Server stored procedure

I believe I am using HOLDLOCK incorrectly.
The reason I think this is because I have a table that acts like a queue. The queue receives its items from the SQL below and gets processed, one by one in a console application. I haven't tested yet but I believe when this console application starts processing this table, during some of the long selects the code below fails. Why do I think that...because I am logging the GameID when grabbing everything from the table queue and processing them one by one in that console application. The funny thing is the games that I believe didn't make it through didn't make it in the log, therefore I dont believe they are being inserted in my queue table and I believe it's because of the HOLDLOCK below.
Thoughts?
MERGE Test WITH (HOLDLOCK) AS GL
USING (SELECT #GameId AS ID) AS NewTest ON GL.ID = NewTest.ID
WHEN NOT MATCHED THEN
INSERT
(
Id,
FailedAttempts,
DateCreated
)
VALUES
(
NewTest.ID,
0,
SYSDATETIME()
);
I suspect your issue is unrelated to your use of MERGE or HOLDLOCK. I see no reason to introduce cumbersome MERGE syntax here, since it provides no benefit, and especially given the potential issues it can cause in other areas. I suggest a very simple INSERT ... WHERE NOT EXISTS:
INSERT dbo.Test(Id, FailedAttempts, DateCreated)
SELECT #GameId, 0, SYSDATETIME()
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.Test WITH (HOLDLOCK)
WHERE Id = #GameId
);
I'd prefer this over just blindly trying to insert and getting a PK violation for the reasons outlined here and here - in almost all cases, forcing SQL Server to try and get an exception instead of checking yourself first will yield worse performance.

SQL Server multi-part identifier '%1' could not be bound with INSERTED pseudo-table

The situation : I'm writing an AFTER INSERT trigger on a table, so I can access to INSERTED pseudo-table, if I have good memory. The trigger is a bit long, so I can't copy / pasta it here, but basically, I'd like to compare the datas of the row I'm inserting (representing a good) with the rows of another table (very similar, representing the wishes), in order to determine if the good inserted corresponds to someone's wishes.
So, I almost finished my trigger, but an error occurred. At a given point, I wrote :
-- Create and open a cursor
IF (#variable1 = INSERTED.MyField)
BEGIN
-- some code
END
-- Deallocate and close my cursor
But I have the following error :
The multi-part identifier "INSERTED.MyField" could not be bound
I thought I could do it, as there is only one line in INSERTED as this moment (I'm right, don't I ?), but it seems I can't.
Can someone explain me why I'm wrong ?
PS : Yes, I've seen this link, or this one, or this one, but they all have a problem with JOIN, and I don't have any JOIN in here
That error indicates SQL is trying to read 'INSERTED' as an alias for another table
IF (#variable1 = INSERTED.MyField)
Try the following to reference the inserted table
IF (#variable1 = MyField from inserted)
Using the inserted and deleted Tables:
http://technet.microsoft.com/en-us/library/ms191300%28v=sql.105%29.aspx
This fixes the syntax and answers the question of why the error is occurring, but comparing inserted to a scalar variable is not recommended. As HLGEM stated, what if you have multiple values in the insert where some match and some don't.
Additionally, Cursors should be a last resort in SQL. In general, cursors are slower and hold up resources. SQL is a optimized for set-based operations and cursors don't leverage that. Without knowing exactly what you are trying to do in the cursor and how much data you are manipulating, I can't say definitely in this case.
One of the many discussions on StackOverflow about Cursors: stackoverflow.com/questions/743183/what-is-wrong-with-cursors

SQL Server 2012 using SELECT in trigger breaks table

So let me first admit that I am a SQL Server newbie.
Here's the deal: I'm trying to create a trigger on a table in SQL Server 2012, and whenever I try any kind of SELECT statement in the trigger, the table quits working (as in NOTHING can be inserted until the trigger is deleted). As soon as I drop the trigger, everything starts working again. If I don't do any SELECTs, everything is peachy. Is there a permission or something somewhere that I'm missing?
Example:
CREATE TRIGGER sometrigger
ON sometable
FOR INSERT
AS
BEGIN
SELECT * FROM inserted
END
GO
Command completes successfully, but the table becomes frozen as described above.
CREATE TRIGGER sometrigger
ON sometable
FOR INSERT
AS
BEGIN
EXEC msdb.dbo.sp_send_dbmail
#recipients = N'someaddress#somedomain.com',
#subject = 'test',
#body = 'test body',
#profile_name = 'someprofile'
END
GO
Works like a charm.
You're may be falling foul of the disallow results from triggers option being set to 1, as it should be.
Note the warning on that page:
This feature will be removed in the next version of Microsoft SQL Server. Do not use this feature in new development work, and modify applications that currently use this feature as soon as possible. We recommend that you set this value to 1.
I suspect that wherever you're running your inserts from is hiding an error message or exception, since you should get:
Msg 524, Level 16, State 1, Procedure , Line
"A trigger returned a resultset and the server option 'disallow_results_from_triggers' is true."
Or, in the alternative, you're working with a database layer that wraps all inserts in a transaction and will roll the transaction back if anything unexpected happens - such as receiving a result set or even just an extra information message saying (x rows affected).
But all of this is dancing around the main issue - you shouldn't be issuing a select that attempts to return results from inside of a trigger. I might have been able to offer more help if you'd actually told us what you're trying to achieve.
If it's the second case, and it's something tripping over the (x rows affected) messages, that can be cured by placing SET NOCOUNT ON at the top of the trigger.
You should never return data from a trigger anyway, mainly for simplicity and maintenance reasons. It's confusing: I did an INSERT but get a resultset back.
If you need to get the values you just inserted, you'd use the OUTPUT clause
INSERT sometable (...)
OUTPUT INSERTED.*
VALUES (...);
This at least tells you that the INSERT gives results.
And it is nestable too as per, say, SQL Server concurrent transaction issue

Debug Insert and temporal tables in SQL 2012

I'm using SQL Server 2012, and I'm debugging a store procedure that do some INSERT INTO #temporal table SELECT.
There is any way to view the data selected in the command (the subquery of the insert into?)
There is any way to view the data inserted and/or the temporal table where the insert maked the changes?
It doesn't matter if is the total rows, not one by one
UPDATE:
Requirements from AT Compliance and Company Policy requires that any modification can be done in the process of test and it's probable this will be managed by another team. There is any way to avoid any change on the script?
The main idea is that the AT user check in their workdesktop the outputs, copy and paste them, without make any change on environment or product.
Thanks and kind regards.
If I understand your question correctly, then take a look at the OUTPUT clause:
Returns information from, or expressions based on, each row affected
by an INSERT, UPDATE, DELETE, or MERGE statement. These results can be
returned to the processing application for use in such things as
confirmation messages, archiving, and other such application
requirements.
For instance:
INSERT INTO #temporaltable
OUTPUT inserted.*
SELECT *
FROM ...
Will give you all the rows from the INSERT statement that was inserted into the temporal table, which were selected from the other table.
Is there any reason you can't just do this: SELECT * FROM #temporal? (And debug it in SQL Server Management Studio, passing in the same parameters your application is passing in).
It's a quick and dirty way of doing it, but one reason you might want to do it this way over the other (cleaner/better) answer, is that you get a bit more control here. And, if you're in a situation where you have multiple inserts to your temp table (hopefully you aren't), you can just do a single select to see all of the inserted rows at once.
I would still probably do it the other way though (now I know about it).
I know of no way to do this without changing the script. Howeer, for the future, you should never write a complex strored proc or script without a debug parameter that allows you to put in the data tests you will want. Make it the last parameter with a default value of 0 and you won't even have to change your current code that calls the proc.
Then you can add statements like the below everywhere you will want to check intermediate results. Further in debug mode you might always rollback any transactions so that a bug will not affect the data.
IF #debug = 1
BEGIN
SELECT * FROM #temp
END

How do I prevent SQL from running transactions simultaneously

I've noticed that MS SQL may begin another transaction just before a previous transaction is complete (or committed). Is there a way how we can ensure a transaction must complete first before the next transaction begins?
My problem is that I want to perform an SQL SELECT almost immediately after an SQL INSERT. What I'm seeing right now is; when the SELECT statement is run; it does not return the (very) recently inserted data.
As I traced this scenario using SQL profiler, I've noticed that the SQL INSERT and SELECT performs simultaneously, as in the SELECT occurs before the INSERT is completed.
Is there a way to fix this problem of mine? thanks!
From the sounds of it, you're looking for the OUTPUT clause
From the examples in the documentation http://msdn.microsoft.com/en-us/library/ms177564.aspx
DECLARE #MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO #MyTableVar
VALUES (N'Operator error', GETDATE());
You can run your transactions in SERIALIZABLE isolation level. In this way you will ensure that the select will be performed after the insert. In lower isolation levels, the select is performed in paralell and returns the snapshot of the data - the way it is seen with all transactions completed before the one that issues select has been started.
I'm guessing you want to get an auto-generated identifier back after the insert? I'm not sure the MSSQL way to do this, but in PostgreSQL, there is INSERT ... RETURNING extension to solve exactly this problem.
http://www.postgresql.org/docs/9.1/static/sql-insert.html
Are you locked into MSSQL?