how to lock a field in table for update in sql - sql-server

Need lock for update a field in a table or maybe pop up a message alter user when this field is update. But still need do be insert or delete a record. i simply try to use command
DENY UPDATE ON JobEmp (Job) TO public
It will not let me do any thing to Job Column, can not add, change or delete. Need some help. Thanks
Using Code
CREATE TRIGGER tr_No_Update_Job
ON dbo.JobEmp
FOR UPDATE
AS
BEGIN
IF UPDATE(Job)
BEGIN
RAISERROR('This column cannot be updated', 16,1)
RETURN;
END
END
But when insert a new record, it also throw the error message. How can i only lock for update?

You can not Grant, Deny or Revok permission on one column of the table you can either deny UPDATE permission on a table on sql server permissions level or you need to create a Trigger to control column level permission.
Table Level Permissions
DENY UPDATE ON OBJECT::[Schema].[TableName] TO [PrincipalName];
Column Level Update Control
CREATE TRIGGER tr_No_Update_Job
ON dbo.JobEmp
FOR UPDATE
AS
BEGIN
IF UPDATE(Job)
BEGIN
RAISERROR('This column cannot be updated', 16,1)
RETURN;
END
END

Do the rollback from after update trigger:
create trigger trJobEmpUpd
on JobEmp
after update
as
if update(Job)
rollback

Have a look to BEGIN/COMMIT TRAN and transaction isolation levels.

If your questions is about Oracle
There is a syntax "for update" that locks a record (not a field)
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4530093713805
-> For SQL server I think the "for update" syntax is "Select ... WITH (updlock)..."
http://technet.microsoft.com/en-us/library/aa213026(v=sql.80).aspx
Note that as been noted by #huMpty duMpty you have to be in a transaction for the lock to be held...
This syntax will issue a row lock on the data selected, which will be released only on commit.
other users will be able to query the data (depends on the DBMS) but not to modify it.
I am pretty sure most other DBMS has the same / similar syntax for locking selected query results, while selecting the data - which allow atomicity - what you got from the "select" will be locked, in the same command, and no one else can intervene in the middle.
If you want to permanently not allow access to a column (for select or update) you should use a different scheme, and allow permisions on a view of the data , or only select permission with stored procedures for editing the actualy data.

Related

what is the purpose of database level trigger in the DDL trigger?

I am confused that what is the on database in the below trigger what is the purpose of using that please let me know what is the use of that
create trigger trmyfirsttrigger
on database
for create_table,alter_table,drop_table
as
begin
rollback
print 'you can not create ,alter,drop table.'
end
The trigger is defined at the database level and is intended to prevent any create, alter and drop statements on any table. That means you cannot create a new table, alter or delete existing tables on the database. This is generally used by DBAs to lock the database from any changes during maintenance & patching.

Inserted records getting committed in DB without committing it manually

I have created a database transaction and I am inserting records in Table1 of H2 DB. But no commits done yet.
In between this process, after executing half of the records, I execute one create statement(created Table2).
Table2 is created and along with it, previous INSERT statements are also getting committed in DB.
After this, I'm inserting more records in Table1, if there is a failure in insertion, I still see records in Table1 which were inserted before create statement for Table2.
Due to this, I see some records in DB even after transaction failure. I was expecting ZERO records in DB.
Why is this happening?
Because create table is a DDL statement and no DML statement. And DDL statement usually commit any open transaction.
If you want to avoid this you should create all objects you need during the import before you import the first record.
EDIT 2019-03-22
Although this topic is a bit old I like to mention one thing which could help. You could create a procedure which uses PRAGMA AUTONOMOUS_TRANSACTION which executes an sql statement via execute immediate
PROCEDURE exec_sql_autonomous(p_sql VARCHAR2)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE p_sql;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
RAISE;
END;
This way you may be able to create a table while the data inserting transaction is in progress without committing it due to the table creation.

How to prevent deadlock of table in SQL Server

I have a table were values can be altered by different users and records of 100k rows.
I made a stored procedure where in, it has a begin tran and at the last part
to either commit or rollback the changes depending on the situation.
So for now the problem we're encountering is a lock of that table. For example 1st user is executing the stored procedure thru the system, then the other users won't be able to select or also execute the stored procedure because the table is currently locked.
So is there anyway where I can avoid lock other than using dirty read. Or a way where I can rollback the changes made without using begin tran, because it is the main reason why the table is locked up.
Yes, you can at least (quick & dirty) enable SNAPSHOT isolation level for transactions. That will prevent locks inside the transactions.
ALTER DATABASE MyDatabase
SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON
See for details.

SQL2012 microsoft trigger

Any idea how to create a after trigger where each where each a user put in their data once. Eg. if someone put in an entry once, then it will be executed. But 2nd time i would like to say 'error message'
The tables I have a table of users, the date and their response. TABLE name is userresponse
This is my coding so far
CREATE TRIGGER [dbo].[prevent_multiple_entry] ON [dbo].[userresponse]
FOR INSERT
AS
IF EXISTS (SELECT Users FROM userresponse)
BEGIN
PRINT 'Error message'
RAISERROR('Each user can only submit to the same question once ',16,1)
ROLLBACK
END
try this one :
CREATE TRIGGER [dbo].[prevent_multiple_entry] ON [dbo].[userresponse]
FOR INSERT
AS
BEGIN
IF EXISTS(SELECT * FROM userresponse AS U, INSERTED AS I WHERE U.User = I.User)
BEGIN
RAISERROR('Each user can only submit to the same question once ',16,1)
ROLLBACK TRANSACTION
END
END
Make sure that the 'nested triggers' and recursive_triggers settings are approriate and think about the fact that allready existing data in that table won't be checked by a trigger.
And SET TRANSACTION ISOLATION LEVEL SNAPSHOT sets a loophole, be carefull.
You also could define a CONSTRAINT...

Selecting Change_Tracking_Current_Version() in SQL Server 2008 table trigger

I am using SQL Server 2008 and Change tracking is enabled on my Database.
On one of my tables in the database, I have created the following Trigger.
CREATE TRIGGER [dbo].[tr_student]
ON [dbo].[Student]
FOR UPDATE,DELETE
AS
BEGIN
SET NOCOUNT ON;
SELECT CHANGE_TRACKING_CURRENT_VERSION()
END
The purpose of this Trigger is - when I update or delete a record in table dbo.Student I should get the the Current change Tracking Version Id.
But when I update/delete a record in the table, CHANGE_TRACKING_CURRENT_VERSION() is not giving the current version_id but the previous version_id. After the trigger is fired,if I execute
select CHANGE_TRACKING_CURRENT_VERSION()
I am getting the correct current version id.
So does the Change_Tracking_Current_Version() id change only after the trigger? Is there any method to get correct Change_Tracking_Current_Version() in the Trigger?
According to the manual, this function
Returns a version that is associated with the last committed transaction.
(Emphasis is mine.)
While your trigger is executing, the transaction is not yet committed. So yes, the new value will be returned after the trigger.
Moreover, there's no way to obtain the new ID in a trigger, because, as specified elsewhere in the manual,
Change tracking is based on committed transactions.
(Emphasis is mine.)

Resources