I have a requirement as below.
I am using SQL Server 2008.
1. Table A (Id)
2. Table B (Id, Attr1, Attr2, Attr3)
Table A and Table B have same no of rows. Id is primary key in both the tables but there is no referential relationship defined.
I have a trigger on Table A for INSERT. If a record is inserted in Table A, I insert the same ID in Table B and calculate few attributes and populate them in Table B for that ID. I am achieving this using a trigger.
Now if the transaction fails in Table B, I don't want the transaction in Table A also to be failed. Irrespective of the trigger succeeds or fails in updating Table B, I want the Table A transaction to be success and not to be dependent on Table B transaction. How do I achieve that?
Helpful link How to create an autonomous transaction in SQL Server 2008
Related
I have a small problem. What I want to achieve is before inserting data to table A, I want to check if this data is in table B and table C.
When tables B and C don't have this data, I'd like to add data from 'inserted' to table B and C (and insert data to table A at the end), but if they have already this row, I don't want to insert anything to table A and B (and don't know to insert anything to table A as well).
Is there any way I can control if the data from inserted will be inserted in table A or not?
suppose I have three tables (table1, table2, table3) linked to a master table tableM.
I have primary key ID in the tableM and foreign key ID in other tables.
suppose I insert a row in tableM, will other tables get inserted a row automatically? Or do I have to write a sp by my own?
Thanks for any advice!
Rows do not get inserted automatically. You have to insert a row into your master table first, and then insert rows into your FK tables afterwards to avoid a FK constraint error.
No, rows are not inserted automatically. Additionally, the INSERT statement could not possibly include columns from these child tables, so even if a row were inserted automatically it could not include data.
You will need to either write a stored procedure (recommended if these child rows are required by the business logic) or simply insert into tables as necessary.
I have a trigger that runs after the update record in the table A, add records to a table B
Now the table B has a trigger that works to ensure that the values entered are correct, when there is a problem with it, the role of a trigger table B is to prevent the entry record (I can not use a unique index because the conditions are in other tables), but I want to avoid only the current record entry, as well as not to prevent the update is done in Table A and not the all good records in this transaction.
the ROLLBACK function is canceling all open transactions.
What is the best way to accomplish this?
Table A and Table B have "Master-Slave" relationship via a FK on Table B. The key is set up for cascade delete and update.
Table B is new and thus does not have as many records as A.
As Table A is inserted, I want Table B to have a new record with the ID field of Table A completed with everything else blank ready for user input.
As Table A is updated, I want Table B to have a new record with the ID field of Table A completed with everything else blank ready for user input if Table A's ID does not yet exist in Table B.
Triggers, I assume?
Many thanks!
I think you need to use an insert trigger on table A.
whenever you insert into A, check if the ID exists in B and if not, then insert into B.
I asked two questions at once in my last thread, and the first has been answered. I decided to mark the original thread as answered and repost the second question here. Link to original thread if anyone wants it:
Handling SQL Server concurrency issues
Suppose I have a table with a field which holds foreign keys for a second table. Initially records in the first table do not have a corresponding record in the second, so I store NULL in that field. Now at some point a user runs an operation which will generate a record in the second table and have the first table link to it. If two users simultaneously try to generate the record, a single record should be created and linked to, and the other user receives a message saying the record already exists. How do I ensure that duplicates are not created in a concurrent environment?
The steps I need to carry out are:
1) Look up x number of records in table A
2) Perform some business logic that prepares a single row which is inserted into table B
3) Update the records selected in step 1) to point to the newly created record in table B
I can use scope_identity() to retrieve the primary key of the newly created record in table B, so I don't need to worry about the new record being lost due to simultaneous transactions. However I need to eliminate the possibility of concurrently executing processes resulting in a duplicate record in table B being created.
In SQL Server 2008, this can be handled with a filtered unique index:
CREATE UNIQUE INDEX ix_MyIndexName ON MyTable (FKField) WHERE FkField IS NOT NULL
This will require all non-null values be unique, and the database will enforce it for you.
The 2005 way of simulating a unique filtered index for constraint purposes is
CREATE VIEW dbo.EnforceUnique
WITH SCHEMABINDING
AS
SELECT FkField
FROM dbo.TableB
WHERE FkField IS NOT NULL
GO
CREATE UNIQUE CLUSTERED INDEX ix ON dbo.EnforceUnique(FkField)
Connections that update the base table will need to have the correct SET options but unless you are using non default options this will be the case anyway in SQL Server 2005 (ARITH_ABORT used to be the problem one in 2000)
Using a computed column
ALTER TABLE MyTable ADD
OneNonNullOnly AS ISNULL(FkField, -PkField)
CREATE UNIQUE INDEX ix_OneNullOnly ON MyTable (OneNonNullOnly);
Assumes:
FkField is numeric
no clash of FkField and -PkField values
Decided to go with the following:
1) Begin transaction
2) UPDATE tableA SET foreignKey = -1 OUTPUT inserted.id INTO #tempTable
FROM (business logic)
WHERE foreignKey is null
3) If ##rowcount > 0 Then
3a) Create record in table 2.
3b) Capture ID of newly created record using scope_identity()
3c) UPDATE tableA set foreignKey = IdOfNewRecord FROM tableA INNER JOIN #tempTable ON tableA.id = tempTable.id
Since I write junk into the foreign key field in step 2), those rows are locked and no concurrent transactions will touch them. The first transaction is free to create the record. After the transaction is committed, the blocked transaction will execute the update query, but won't capture any of the original rows due to the WHERE clause only considering NULL foreignKey fields. If no rows are returned (##rowcount = 0), the current transaction exits without creating the record in table B, and returns some sort of error message to the client. (e.g. Error: Record already exists)