How to make only one user can insert data at a time in SQL Server? - sql

I have a SQL Server database, multi-user can insert to it.
But for many reasons, I want only 1 user can insert at a time.
Example:
User 1 want to insert 100 record, while user 1 is inserting (100 record not saved to table). Other user can not insert to the table.
I have thought to use a flag, but I want to find another way.
Is there any SQL statement that can do that?
Thanks for reading!

It seems that you need to use
INSERT INTO TABLE with (rowlock)
Read the following post to have a better understanding.
Using ROWLOCK in an INSERT statement (SQL Server)
Updated
SQL supports us to handle 1 record at a time e. And your case is to want multiple records to handle serialized format.
I think the best you put into the temp table, there is a window service running real-time (Background service: using quartz job or hangfire): insert and delete then the temporary table with a column named IsInserted.

For that purpose you can used table lock or row loack concept.
ALTER TABLE Table_name SET (LOCK_ESCALATION = < TABLE | AUTO | DISABLE > –One of those options)
For more details you can also visit this link
locking in SQL Server

Related

Executing Insert command at the same time writes the data twice to database despite a check

I need to check whether similar data exists in the database and skip that insert. This question might look like a duplicate but I did not find any solutions.
I am using PostgreSQL DB and I have an SQL query
INSERT INTO table_name (name, dob, mobile)
VALUES ('sam', '23-05-2000', '8070605040');
If I run this command twice then it should only be inserted once after checking for the combined uniqueness of dob and mobile i.e. if I enter data like ('tom', '23-05-2000', '8070605040'), it should not be entered. My existing code works when the command runs one after the other.
But if I run the command at the same time on 2 devices by the press of a button then the record is entered twice.
Result after Running code one after the other
name dob mobile
sam 23-05-2000 8070605040
Result if the command is executed at the same time
name dob mobile
sam 23-05-2000 8070605040
sam 23-05-2000 8070605040
If there is even a second delay then the existing code works fine. But executing literally at the same time does not check as it is not written to the database yet.
I also do not want to add a unique condition on the table itself as I don't understand the data correctly and would like to do this as an SQL query.
How can I check and prevent this from happening.
Thanks.
If I run this command twice then it should only be inserted once after checking for the combined uniqueness of dob and mobile
This is only true if dob/mobile is declared unique or has a unique index. Presumably, you need:
alter table table_name add constraint unq_table_name_dob_mobile unique (dob, mobile);
With a unique index/constraint, the database ensures the data integrity. The database will not allow duplicates into the table, no matter how hard the application tries.
If you want to manually check the uniqueness of the record, you can use a transaction and lock the whole table:
BEGIN;
LOCK TABLE tbl IN EXCLUSIVE MODE; -- only allow read access
SELECT * FROM tbl WHERE a = 1 and b = 2;
--- if not existed, insert new record here
COMMIT;
This has poor performance and should only be used for this one specific need. The best solution is always use a UNIQUE INDEX.

SQL Server bulk insert for large data set

I have 1 million rows of data in a file, I want to insert all the records into SQL Server. While inserting I am doing some comparison with existing data on the server, if the comparison satisfied I will update the existing records in the server or else I will insert the record from the file.
I'm currently doing this by looping from C#, which consume more than 3 hours to complete the work. Can anyone suggest idea to improve the performance?
Thanks,
Xavier.
Check if your database in Full or Simple recovery mode:
SELECT recovery_model_desc
FROM sys.databases
WHERE name = 'MyDataBase';
If database is SIMPLE recovery mode you can create a staging table right there. If it is in Full mode then better create Staging table in separate database with Simple model.
Use any BulkInsert operation/tool (for instance BCP, as already suggested)
Insert only those data from your staging table, which do not exist in your target table. (hope you know how to do it)

SQL: Get real time data from different database

I want to insert data from database1 into database2 when something changes. Like a trigger but the thing is I am not allowed to create a trigger in database1.
I basically need to insert certain data into a table from a database into another database as they happen.
Any suggestions would be great!
Thanx
You can create a program to do that, there are many ways instead but I think this is the straightforward and easy one.
For example if you work with SQL server you can create C# code that connect to the two databases and check for data in the first one then send it to the second.
For example:
you can create a trigger for the first DB tables you want to check them, then you can create a web service that check if the trigger fire, it will get the data from first database and send it to the second, this will be better to enhance and you can change the code to do whatever you want without making any changes from the database side
MS SQL Server Replication
I think suitable for you is Transactional Replication
Transactional replication is asynchronous but close to real time
What about the merge operator ?
Merge operator will commit changes into the target table from the source table when something change.
As you cannot use trigger this cannot be a real time process but with a process scheduler like SQL Agent, you can run it each 10 seconds depending on your table size.
https://msdn.microsoft.com/en-us/library/bb510625.aspx
You can do it when your source come from multiple table by using CTE like that :
With TableSources As
(
Select id,Column1, Column2 from table1
UNION
Select id,Colum1,Column2 from table2
)
MERGE INTO TargetTable
USING TableSources ON TargetTable.id=TableSources.id
WHEN NOT MATCHED BY Target
Insert(Column1,Column2) Values(Column1,Column2)
WHEN NOT MATCHED BY Source
Delete
WHEN MATCHED
Update Set Column1=TableSources.Column1, Column2=TableSources.Column2
;

How to find when a row is inserted or updated in SQL Server table

I have a table in SQL Server but there is no column to show when the value is inserted into the table. And also I don't want to create a one.
Is there a way that I can find the time and date when some one has inserted a row into a SQL Server 2008 table or when it is updated?
If you don't want to modify your existing tables, the only way to go is to create another table to log the activities to. Then you can use ON INSERT / ON UPDATE triggers on the source tables and log the time and date of inserts and updates to the log table.
You can use On Insert and On Update Triggers in sql server 2005/2008 and your required fields are available in inserted and updated tables, but if you need to use this information later need to add a new table and log your information on to that!
I myself for doing such stuff like this always add 2 column to my tables
LastActivityBy relation to user table
and
LastActivityOn datetime
so you don't need to use any other table.
If you dont want to alter your existing schema, create a audit table and create trigger on source table to update audit table.

Are writing triggers in MS SQL server the same as writing them in MS Access?

I have written the following trigger in SQL server:
create trigger test_trigger
on invoice -- This is the invoice table
for insert
as
declare #invoiceAmount int -- This is the amount specified in the invoice
declare #custNumber int -- This is the customer's id
--use the 'inserted' keyword to access the values inserted into the invoice table
select #invoiceAmount = Inv_Amt from inserted
select #custNumber = cust_num from inserted
update customer
set amount = #invoiceAmount
where Id = #custNumber
Will this be able to run in MS Access or is the syntax different?
The Access database engine (formerly called Jet) does not have triggers and regardless has no control-of-flow syntax e.g. a PROCEDURE must consist of exactly one SQL statement.
Tell us what you really want to do and there could be an alternative syntax.
For example, you could create a new key using a UNIQUE constraint on invoice, (cust_num, Inv_Amt), a FOREIGN KEY customer (id, amount) to reference the new key, a VIEW that joins the two tables on the FOREIGN KEY columns and exposing all four columns, then INSERT into the VIEW rather than the table 'invoice'; you may want to use privileges to prevent INSERTs to the base table but user level security was removed from the new Access 2007 engine (called ACE).
But, if you don’t mind me saying, I think your trigger doesn't reflect a real life scenario. A column vaguely named 'amount' in table 'customer' to hold the most recent invoice amount? What about when the inserted logical table contains rows for more than one customer? As I say, I think you need to tell us what you are really trying to achieve.
Access doesn't have triggers
Your trigger that you show here will bomb out since it does not take into account multirow updates the moment someone updates more than one row (and don't say it won't happen because it will better to practice some defensive coding)
Triggers fire per batch not per row, please read Multirow Considerations for DML Triggers
join inserted pseudo table and the invoice table instead to update the values...that works for 1 and more than 1 row
They may be coming in Access 2010? http://blogs.msdn.com/access/archive/2009/08/13/access-2010-data-macros-similar-to-triggers.aspx
MS Access doesn't have triggers.
That is, the the Access Jet engine (which creates .mdb files). If Access is connecting to a database server, then it will use whatever triggers are in that database.
I've never come across triggers in Access unless it's dealing with ADP on SQL Server. So your answer is yes, it's the same if you're on SQL Server for the backend, and no if the table is stored in Access.