How can I create a Trigger that delete a column only if all values on a specific field are null?
What do you mean "create a trigger"? Do you mean that you want an update/delete trigger that would delete the column at the point when all the values become NULL?
If so, that is not possible. "Deleting a column" is really alter table drop column. In the Remarks section for the create trigger documentation:
Additionally, the following Transact-SQL statements are not allowed
inside the body of a DML trigger when it is used against the table or
view that is the target of the triggering action . . .
ALTER TABLE when used to do the following: Add, modify, or drop columns. Switch partitions. Add or drop PRIMARY KEY or UNIQUE
constraints.
Hence what you want to do is not possible. Further, I don't understand why you would want to do it. A data-driven change to the data structure seems strange. I am guessing that your data structure really wants to be a junction/association table, but you don't provide enough information to speculate further.
Related
Is it possible to change a global temporary table in Oracle from PRESERVE ROWS to DELETE ROWS?
I have tried the following command and I get a syntax error. If it is possible, what is the correct syntax?
ALTER TABLE BLOCKING_RESULTS ON COMMIT DELETE ROWS
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
It is not possible. The valid syntax is documented, and doesn't include the ability to change this. Not being able to change this isn't listed explicitly as one of the restrictions for GTTs, but that only refers to things that are allowed for other types of table.
You'll have to drop and recreate the table with the new on commit clause.
Tom Kyte made a succinct comment on this way back in 2003.
(I'd speculate that it might be related to the statement that table locks are not acquired on temporary tables.; though how it lets you add columns without that being an issue is interesting. Altering the preservation while sessions have data in the GTT might have odd side-effects anyway...)
According to this example/article in step 7:
-You cannot alter a temporary table to change its data duration.
-You must drop and create it agin.
http://oracle-plsql-tech.blogspot.com.tr/2013/03/temporary-tables.html
If your case is same.
syntax you have used is wrong. Try PL/SQL alter table syntax.
I am trying to delete a row from a table in my database, but first I have to delete rows that correspond with that row via foreign keys.
I am using an instead of trigger on the main table and inside of it, I am first deleting child rows from other tables that correspond to that main row, and then I want to delete the main row. But (as expected) the main row is not being deleted because it is an INSTEAD OF trigger.
If I try to delete the main row in the instead of trigger I am getting error:
INSTEAD OF triggers do not support direct recursion. The trigger execution failed
If I try to use AFTER DELETE trigger, I get error:
The DELETE statement conflicted with the REFERENCE constraint [...]
because I am trying to delete the row that corresponds with other rows in other tables.
I've been trying to think of an idea to solve this problem, but I'm stuck and I couldn't find a working solution on the Internet. I have a feeling that I'm missing something obvious, but I can't seem to find it.
Thanks and take care guys!
The problem has been resolved with help of #ZLK using cascading deletes or:
#ZLK: You also have the option of altering the table to not check the constraint. For example, alter table X nocheck constraint myConstraintName, then doing the delete statement / data manipulation (e.g. in an after delete trigger) then turning the constraint back on alter table X check constraint myConstraintName
I have four tables ie.
custAddress
custCompany
custContact and
custInfo
All of the table has 'cId' field common.
I have a interface in MVC3 view from which I will take inputs for all field except 'cId'. When I take input from the interface all of the above tables must be filled.
Also when I delete data, once I delete data from one table all the data from the other three table should be deleted.
I don't know how to use trigger for this. Please explain how can I do this using trigger or any other way. Any help is appreciated.
To me it sounds more like a database design problem. You do not need trigger here. Keep one of your table as primary (may be CustInfo) and have other table dependent(foreign key relationships) on this. Use cascade delete constraints on dependent tables. When you delete data from CustInfo, cascade delete constraint will take care of deleting corresponding data from dependent tables.
I have an ItemComments table that has one column with a foreign key constraint linking back to an item entry in a second table. I see this as a one-to-many relationship as each item in the second table can have many comments, but no two items can be associated with the same comment entry in the ItemComments table, so a many-to-many relationship does not apply.
PROBLEM:
I want to define a constraint on this column that will prevent the foreign key value from being updated, i.e. I want to prevent someone from accidentally changing the item ID that a specific ItemComment entry is associated with. I'm not very familiar with the expression formatting of constraint check and was curious what the syntax would be for such an action. Or is there another more straightforward way of accomplishing this? Thanks for the help.
UPDATE
Is it better to implement a cross-reference table as you would in a many-to-many relationship to enforce referential integrity in this way? Or is that adding more overhead than is necessary?
You can always use a trigger. Something like:
create trigger dml_PreventUpdate
on YourTable
after update
as
if UPDATE(ItemId)
rollback
There's two types of Data Manipulation Language (DML) triggers. There's an INSTEAD OF and then an AFTER/FOR trigger (AFTER and FOR function the same way). An INSTEAD OF trigger, as the name implies, executes prior to the transaction taking place. An AFTER trigger, again as the name implies, executes after the triggered action.
Basically all this trigger is doing is testing to see if the ItemId column is updated from the UPDATE statement run against the table, YourTable. This trigger will fire every time there is an UPDATE against YourTable, but it will only ROLLBACK the transaction if ItemId is an updated field.
Our company uses Sybase and we are planning on setting up a Mobilink system (data replication system). We therefore need to change from using autoincrement columns to global autoincrememnt columns.
My question is what steps do I need to take to get this working properly. There is already thousands of rows of data that used the regular autoincrement default.
I'm thinking I need to create a new column with a default of global autoincrement, fill it with data (number(*)), switch the PK to it, drop the old FK's, drop the old column, rename the new column to the old one, then re-apply the FK's.
Is there an easier way to accomplish what I need here?
thanks!
That's generally the way to go about it. But there are some specific statements you make that cause me concern. Also the sequence. I am not sure of your experience level, the terms you use may or may not be accurate.
For each table ...
... switch the PK to it
What about the FK values in the child tables ? Or do you mean you will change them as well ?
... drop the old FK's
Ok, that's the constraint.
... drop the old column, rename the new column to the old one, then re-apply the FK's.
What exactly do you mean by that ? Add the FK constraint back in ? That won't change the existing data, it will apply to any new rows added.
Hope you see what I mean by the sequence of your tasks is suspect. Before you drop the old_PK_column in the parent, you need to:
Add the dropped FK constraints in each child table.
For each child table: UPDATE all the FK values to the new_PK_column.
Then drop the old_PK_column.
you're just changing the way PK values are generated, so it's enough to:
ALTER TABLE <table>
modify <column> default global autoincrement (1000000);
to use a partition size of 1,000,0000
Also make sure you set the global database identifier in each db, for example:
SET OPTION PUBLIC.global_database_id = 10;
So the next PK that will be generated is 10,000,001