Strange error when using output clause on an update statement? - sql

Firstly, a lot of people are unfamiliar with output in my experience. If so, this link is very handy: Hidden Features of SQL Server
I have the following update statement:
UPDATE lease_deal.lease_budget
SET change_type = NULL
OUTPUT inserted.*
WHERE ISNULL(change_type, '') = ''
Although I thought this would return the updated records for me I'm receiving the following error:
Msg 334, Level 16, State 1, Line 9 The target table
'lease_deal.lease_budget' of the DML statement cannot have any enabled
triggers if the statement contains an OUTPUT clause without INTO
clause.
I know I can successfully create a temporary table and redirect the updated records there using the output statement, but why can't I return it to the IDE? I'm sure (certain) I've been able to do this before but can't seem to find a suitable example anywhere to help me understand what I'm doing wrong. Is this simply not possible when you have triggers on a column that you're updating?

This
http://msdn.microsoft.com/en-au/library/ms177564.aspx
says this
If the OUTPUT clause is specified without also specifying the INTO keyword, the target of the DML operation cannot have any enabled trigger defined on it for the given DML action. For example, if the OUTPUT clause is defined in an UPDATE statement, the target table cannot have any enabled UPDATE triggers.

Related

pyodbc - insert into 'select' not working

I am trying to run INSERT INTO SELECT statement in cur.execute. The code executes without any error, but there are no records inserted in the table.
Here is the table data:
I execute the following query,
cursor = conn.cursor()
query = 'INSERT INTO destination_test_hist SELECT * FROM destination_test'
cursor.execute(query)
conn.commit()
Where am I going wrong? I need some assistance
Syntax-wise, I don't see any errors.
Just a few simple things to check to be sure:
Check that your connection is correct and you are checking that server/db, your source table(in this case destination_test) and target table (in this case destination_test_hist) are correct.
Check your database environment and relevant tables in the same. You might have checked the QA test environment maybe or post the query with output of no records with database name and tables.
Also, at programming level it may appear that it might not have got executed in the database do debug the query output what it returns at programming level too.

Using conditional to Update OR Delete

I have written a stored procedure that updates a table and then writes old records to a historical table, using OUTPUT deleted.*
I am now looking to update the procedure and include an #option parameter, which will be either 1 or 2. If the option is 1, the records will be updated in the target table. If it is 2, then they will be deleted from the table.
Is there any way to write in a conditional that will update or insert based on this input parameter? I can write it as
IF #option = 1
BEGIN
...updates...
END
IF #option = 2
BEGIN
...deletes...
END
but there are many fields being updated/deleted and the process repeats three more times, so I am trying to make it more concise.
I have tried doing (CASE #option WHEN 1 THEN UPDATE WHEN 2 THEN DELETE) table1 ... but that is incorrect SQL. I have considered using MERGE and including the conditional, something like WHEN MATCHED AND #option = 1 THEN but am getting syntax errors there. I am also not too familiar with MERGE so if anybody has any insight into this process, it would be greatly appreciated.
To clarify, my question is:
Is there any way to conditionally UPDATE or DELETE (or do other DML operations)?
MERGE works by inserting records that don't exist and updating those that do, which is a common scenario. Even so it's not much more concise than separate INSERT and UPDATE statements, since you still have to supply the statements separately (just wrapped inside a single MERGE statement.
Conditionally updating or deleting is not a common scenario in my experience, so there's not a concise SQL syntax to do so.
I would note that fields aren't specified in a DELETE so there is some difference in the syntax anyways. I think having an if block that separates the UPDATE and DELETE is going to be as concise as you can get.

Suppress result sets from trigger

I have a sql statement that first updates, then selects:
UPDATE myTable
SET field1=#someValue
WHERE field2=#someValue2
SELECT 1 returnValue
The process that consumes the reults of this statement is expecting a single result set, simple enough.
The problem arises because an update trigger was added to the table that produces a result set, i.e. it selects like so:
SELECT t_field1, t_field2, t_field3 FROM t_table
The obvious solution is to split up the statments. Unfortunatley, the real world implementation of this is complex and to be avoided if possible. The trigger is also nessecary and cannot be disabled.
Is there a way to supress the results from the update, returning only the value from the select statement?
The ability to return result sets from triggers is deprecated in SQL Server 2012 and will be removed in a future version (maybe even in SQL Server 2016, but probably in the next version). Change your trigger to return the data in some other way. If it is needed just for debugging, use PRINT instead of SELECT. If it is needed for some other reasons, insert the data into a temporary table and perform the SELECT from the calling procedure (only when needed).

How to disable nesting of triggers at table or trigger level in SQLServer?

Using SQL Server 2012, is it possible to have nested triggers enabled at the server/database level but to disable nesting on one specific table/trigger?
I think that you should be able to achieve your purpose by using the TRIGGER_NESTLEVEL() function, which is available since SQL Server 2008:
Returns the number of triggers executed for the statement that fired the trigger. TRIGGER_NESTLEVEL is used in DML and DDL triggers to determine the current level of nesting.
You could alter the code of the relevant trigger to add the following statement just after the BEGIN keyword. The trick is to dynamically compute the object_id of the current trigger, which TRIGGER_NESTLEVEL() expects as first argument:
IF TRIGGER_NESTLEVEL(
( SELECT object_id FROM sys.triggers WHERE name = 'MyTrigger' )
) > 1 RETURN
This will actually prevent the given trigger to execute recursively.
Another option is to use TRIGGER_NESTLEVEL() without arguments. This returns the number of times all triggers have been executed for the statement. My understanding of your use case is that the first solution should be what you need.

Informix SQL update command error 746

I tried to update the field "contract_id" in the table "contract_scan_image".
However, the update was failed and an error "746: Field contract_id and type of contract_scan_image cannot be updated!" was shown.
My SQL command is:
update contract_scan_image
set contract_id = '14864730'
where contract_id = '1486473'
and type = 'RM'
and account = '00193400944'
Does anyone know what happened and how to fix it?
Error message -746 is for user-defined errors. It typically is used in stored procedures in a RAISE EXCEPTION statement:
RAISE EXCEPTION -746, 0, "Field contract_id and type of contract_scan_image cannot be updated!"
The actual message text for error -746 in the message files is:
%s
That is, it prints the string it is given as a string.
So, you are going to need to track down the triggers and stored procedures invoked by those triggers on the contract_scan_image table, and deduce from where the error is generated what you are doing wrong. Superficially, though, it appears that you are not allowed to alter the contract ID, yet that is what you are trying to do.
First things first, I would take a look at a list of Reserved words in SQL - https://drupal.org/node/141051
I would get in the habit of surrounding fields with `` See below:
update contract_scan_image
set `contract_id` = '14864730'
where `contract_id` = '1486473'
and `type` = 'RM'
and `account` = '00193400944'
** Note - type is a reserved word
The error is caused by something being triggered. Then no table can be modified by UPDATE command.
Finally I deleted the record I want to update. Then added back the modified record.
I copy the error description here from the net for reference.
BTW, I asked my supervisor and he said he did trigger something to cause this. (He didn't tell me how to un-trigger it...)
-746
THE SQL STATEMENT IN FUNCTION, TRIGGER, OR IN STORED PROCEDURE name VIOLATES THE NESTING SQL RESTRICTION
Explanation
If a table is being modified (by INSERT, DELETE, UPDATE, or MERGE), the table can not be accessed by the lower level nesting SQL statement.
If any table is being accessed by a SELECT statement, no table can be modified (by INSERT, DELETE, UPDATE, or MERGE) in any lower level nesting SQL statement.
System action
The SELECT, INSERT, DELETE, UPDATE or MERGE SQL statement failed.
Programmer response
Remove the failing statement from the named function, trigger or the stored procedure.
SQLSTATE
57053