I have a web form with several fields first field is Employee Number which is having "EMP - 0001" Format.i'm generating next Employee number by considering the last Emp Number added and converting the latter part to integer and add one
ex: split EMP - 0001 -> get 0001 -> convert it to integer -> add one -> generate next no as EMP - 0002
Next Employee Number should be visible to the user.my issue is when there are multiple users using the system.imagine that one user opens the web Form and doesn't save the record.his Employee Number is EMP - 0002.another user opens the web form he also sees the EMP no as 0002 because last record is not saved yet.2nd user saves the records he gets the Number 0002.1st user then saves the record.so at last i've got duplicate EMP Numbers in my database.what kind of scenario should i follow to over come this situation
The only way to accurately predict their ID is to put in a blank record, get the ID used, then when they enter the form, update the record with their information. However, if they quit the form, you're left with a blank record.
Insert the record on the DB and get the ID it returns. You won't have concurrency issues there if you're opening and disclosing your connection correctly.
Your current approach is prone to concurrency issues as you pointed out & I will not recommend it you. You have the following options.
Use an Identity column in your database table as a serial column (The database automatically increments the identity column on every insert row operation- you don't have to specify it through code)SQL Server Identity
Use a database sequence (Depeding on your database version & its support - A database sequence returns a unique integer value - this can also be cached, presented on form once the form loads - once generated, same sequence is never generated again)
Use a database trigger to automatically update the Id column on every row insert
Depeding on your requirement, you can pick one option.
After saving the record you can give the user message tah record is saved and your Employee numnber is "EMP - 0002".
Related
I am implementing a form on table that allows the end-user to create a new project. This form contains a shuttle that allows the user to select the disposal site(s)(1+) that the project pertains to. I would like to use the output of the shuttle values to populate an association table between projects and disposal sites which is a many to many relationship.
This is my approach so far:
Created an additional VARCHAR2(4000)in the projects table to store the shuttle output (called 'Shuttle'). The shuttle output in this column looks something like 'CA-AT-D109Z2:CA-AT-D115:CA-AT-D174Z2'.
Created a process to take separate based on ':' and then add the values to the association table using the PL/SQL code:
Declare
Cursor c_values
is
Select
t.column_value As disposal_sites
From
Table ( apex_string.split(:P28_SHUTTLE, ':') ) t
Where
t.column_value Is Not Null;
Begin
for c in c_values loop
insert into MP_MDB_PROJECT_2_DSITE (PROJECTIDFK,DISPOSALSITEIDFK)
values (:P28_PROJECTNUMBER,c.disposal_sites);
end loop;
End;
The process/code enters the values from the shuttle into the association table in a loop as expected for the the disposal site but remains blank for projectidfk (the key that is '1' in the 1:m relationship). The code doesn't throw an error so I am having trouble debugging.
I think perhaps the problem I am having is that project number is computed after submission based on the users selections.Therefore, when the process run it finds :P28_PROJECTNUMBER to be null. Is there a way to ensure the computation to determine :P28_PROJECTNUMBER takes places first and is then followed by the PL/SQL process?
All help appreciated
If the form you're implementing is a native apex form, then you can use the attribute "Return Primary Key(s) after Insert" in the "Automatic Row Processing - DML" process to ensure that the primary key page item contains inserted value for any processes execute after this process.
Just make sure the process that handles the shuttle data is executed after the DML process.
I have 2 Tables :
T_Customer
T_Address
In T_Customer Table have T_Address Foreign Key.
on Web Page Created form Where Customer can add there Details like First Name, Last Name, Address etc.
When Customer Submit form then Adddress details should insert in T_Address table And T_Address ID goes To T_Customer Table is it possible to Create 2 insert operations on one button click?
Is Joins is possible in this?
A single INSERT statement can only affect one table, albeit that you might have some triggers that in turn affect other tables. However, your question was specifically about an action on one button click. This is very possible, and indeed highly advisable. Simply create yourself a single stored procedure and pass it as parameters all the fields required for both Customer and Address tables.
Then within your Stored procedure you can have two inserts, one to Customers and one to Address. If you have a referential integrity constraint, then you must insert customers before address.
The advantage of this approach, is that all commands within a stored procedure are covered by the same transaction: it all succeeds or all fails, and requires only one round trip to the database, in turn being quicker and using less resources.
I have used this code to generating an auto number:
DECLARE
ACC_NEW_ID NUMBER:=0;
BEGIN
if :acc_info_id is null then
SELECT MAX(NVL(ACC_INFO_ID,1000))+1 INTO ACC_NEW_ID FROM ACC_INFO;
:ACC_INFO_ID := ACC_NEW_ID;
end if;
END;
This code is working perfectly, but when I create one further record without clicking save button it creates the same number. For example: id is 1003 and after posting the record, I clicked new record button instead of save button, It generates the same 1003 number instead of 1004 as I expected.
Your code queries the records in the table, and returns the maximum ID that it can see at that point in time (i.e. it won't see uncommitted records), and adds one to it.
If it generates 1003 but no record with this value is saved into the table, of course you should expect it to not find it!
As far as that is concerned, it "works perfectly" and correctly. If, however, the intention is to generate a unique ID value for each record, this approach is flawed and will fail in any normal system due to concurrency.
Instead, if you need a unique ID you should use an Oracle SEQUENCE instead, which guarantees uniqueness.
I am developing a .ASPX page with following design
Firstname
Lastname
Address
City
Mobile
This is represented to user with labels and textboxes.
When user clicks on Save button, data is saved in SQL Server 2008 Express database table.
Table has following schema
RecordNo-int(PK)
Firstname-nvarchar(50)
Lastname-nvarchar(50)
Address-nvarchar(500)
City-nvarchar(50)
Mobile-nvarchar(12)
At the time of page loading, I also display recordno to user.
This record number is generated based on how many records are there in the table.
I get the number of records and just increment it by 1 and put it against RecordNo.
Now, if this is happening on one PC, it works fine.
First entry will be represented with RecordNo 1
and so on.
But if, there is no record in the table, and the same page is opened by 4 different users at the same time, then all will
be represented with RecordNo 1.
and then, user who first click save button, will be able to save the data perfectly.
But other three users will encounter error, because they are entering information with RecordNo 1, which is already entered.
How do i overcome this?
Each new entry should be given new and unique RecordNo.
Is there any way i can do this?
Why to take headache of showing the number of entries you just set the primary key column to Identity(1,1) which will increment that column value by 1 every time a new row is inserted. This is how 'n' number of user will be able to make entries concurrently.
Set an Identity Cloumn as :
RecordNo int Identity(1,1) Primary Key
In Identity(1,1) first 1 is Starting Value and Other is Increment Value.
Use the code below if you don't want to use Identity:
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY RecordNo ASC) AS RecordNumber,
FirstName,LastName,Address,City,Mobile from yourTableName) AS RecordNo
Make RecordNo an IDENTITY(1,1) field and forget about all your logic to generate the key. IDENTITY does this for you automatically.
If you require you can call SCOPE_IDENTITY() after the record is inserted to capture the generated value.
I am unsure on how to do this 'best practice' wise.
I have a web application (asp.net VB) that connects to an MS SQL server 2012. Currently when the page loads the app connects to a DB table and gets the last ID and adds 1 to it and displays this to the user. When the user submits the form the new ID is saved to the DB.
The problem being the app may be opened by 2 users at the same time and therefore they will get assigned the same ref number which will cause problems when the data is saved.
How can I assign different numbers to different users if the app is opened at the same time without saving unnecessary data?
You have multiple solutions for this, I'll try to outline a few approaches. (I'll assume that you need to insert things into a DB that I'll call "orders".)
First of all, you can move the ID-generation to the moment when the order is actually inserted, and not at the moment when the user start to enter the data. That way, you do not generate an ID for a user that never completes the form. Also this scenario is easy to accomplish using autoincrementing values in sql server. You can, for example do:
-- create a table with an identity column
create table Orders (
ID int identity(1,1) not null,
Description nvarchar(max) not null
);
-- insert values, without specifying the ID column
insert into Orders (Description) values ()
-- select the row back
-- returns 1, 'My First Order'
select * from Orders;
Another way to do this is to use SQL Server Sequences. These are things that do nothing except generate numbers in a row. They guarantee that the numbers won't be repeated, and always keep count of the current value, i.e.
-- create a sequence
create sequence OrderIdSequence
start with 1
increment by 1;
-- get the next sequence value
select next value for OrderIdSequence