If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Database Server Software > DB2 > To make a non-key field unique

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 02-22-10, 02:31
qxz qxz is offline
Registered User
 
Join Date: Apr 2002
Posts: 84
Question To make a non-key field unique

Dear All,

I encountered a tricky problem, a non-key field (string type) must be unique. It is with the format of YYYY-Order_No, while YYYY is current year and Order_No should be incremental. We use '2010' || '-' || 1+Select count (*) from Order_table to generate the string.

The problem is, when there are two persons access to the query at the same time, the value will be duplicated. Any solution? As it is already a production database, we cannot change much on the schema.

Thanks!
XZ
Reply With Quote
  #2 (permalink)  
Old 02-22-10, 02:57
umayer umayer is offline
Registered User
 
Join Date: Dec 2005
Posts: 273
create an unique index on that field.

If two user try to insert the same value, the second one will fail and can ( automaticly ) recalculate the Orderno and retry the insert
Reply With Quote
  #3 (permalink)  
Old 02-22-10, 03:44
qxz qxz is offline
Registered User
 
Join Date: Apr 2002
Posts: 84
The problem is we have some historical data with null values in the field. Any solution?

Thanks.


Quote:
Originally Posted by umayer View Post
create an unique index on that field.

If two user try to insert the same value, the second one will fail and can ( automaticly ) recalculate the Orderno and retry the insert
Reply With Quote
  #4 (permalink)  
Old 02-22-10, 04:02
umayer umayer is offline
Registered User
 
Join Date: Dec 2005
Posts: 273
in that case: create an UNIQUE WHERE NOT NULL index ...
Reply With Quote
  #5 (permalink)  
Old 02-22-10, 06:08
tonkuma tonkuma is online now
Registered User
 
Join Date: Feb 2008
Location: Japan
Posts: 2,194
"WHERE NOT NULL" is supported on DB2 for z/OS and iSeries.
It is not supported on DB2 for LUW.
Reply With Quote
  #6 (permalink)  
Old 02-22-10, 07:47
stolze stolze is offline
Registered User
 
Join Date: Jan 2007
Location: Jena, Germany
Posts: 2,662
We don't know on which product the OP is working. So if it is indeed DB2 LUW, one option would be to add a trigger that does the weak uniqueness checks.
__________________
Knut Stolze
IBM DB2 Analytics Accelerator
IBM Germany Research & Development
Reply With Quote
  #7 (permalink)  
Old 02-22-10, 10:00
Cougar8000 Cougar8000 is offline
Registered User
 
Join Date: Nov 2005
Location: IL
Posts: 554
you said you already have historical data in there and some of it is NULL. If you have more then one record where this data is NULL you are SOL as you can only have one NULL in your UNIQUE index. You would have no other choice but to do table redesign like it or not.

Run a SQl to find out if you have more then one NULL. Sounds like you will.
__________________
--
IBM Certified DBA on DB2 for Linux, UNIX, and Windows

DB2 v9.1.0.2 os 5.3.0.0
Reply With Quote
  #8 (permalink)  
Old 02-22-10, 10:37
Lenny77 Lenny77 is offline
Registered User
 
Join Date: Jul 2009
Location: NY
Posts: 886
Arrow

You can use something like this:

Code:
select char(year(current date)) || '-' ||char(coalesce(count (*), 0) + 1 ) 
from Order_table
Lenny
Reply With Quote
  #9 (permalink)  
Old 02-22-10, 11:38
MarkhamDBA MarkhamDBA is offline
Registered User
 
Join Date: Dec 2008
Location: Toronto, Canada
Posts: 381
Quote:
Originally Posted by qxz View Post
Dear All,

I encountered a tricky problem, a non-key field (string type) must be unique. It is with the format of YYYY-Order_No, while YYYY is current year and Order_No should be incremental. We use '2010' || '-' || 1+Select count (*) from Order_table to generate the string.

The problem is, when there are two persons access to the query at the same time, the value will be duplicated. Any solution? As it is already a production database, we cannot change much on the schema.

Thanks!
XZ
i think you should had have 2 cols - year and order_number - and make order_number an indentity column. Will work much much faster. you wll not get dups. Select count (*) is bad in the first place - takes too long. And I agree with Cougar8000 - you need to re-design it.

In order to keep the NULLs if there is more than one, you can
- create another table with same structure but allowing NULLs in order_num col
- move all records with NULLs to this table
- alter original table to make order_number an identity col
- create a view on both tables with union all
- make users to use the view (if it has same name as original table they will not notice any difference )
__________________
DB2 v9.5 ESE on AIX v6.1/ v9./10 on z/OS

Last edited by MarkhamDBA; 02-22-10 at 11:49.
Reply With Quote
  #10 (permalink)  
Old 02-22-10, 11:48
Cougar8000 Cougar8000 is offline
Registered User
 
Join Date: Nov 2005
Location: IL
Posts: 554
I totally missed it the first time. You are doing this for every new record?

Quote:
'2010' || '-' || 1+Select count (*) from Order_table
How is your performance?
__________________
--
IBM Certified DBA on DB2 for Linux, UNIX, and Windows

DB2 v9.1.0.2 os 5.3.0.0
Reply With Quote
  #11 (permalink)  
Old 02-22-10, 12:02
MarkhamDBA MarkhamDBA is offline
Registered User
 
Join Date: Dec 2008
Location: Toronto, Canada
Posts: 381
we have one of those - instead of using identity col or a sequence, they created a trigger which finds max(col), adds 1 and inserts it into the table. performance is awful. we are going to change it to identitly column as soon as we can.
__________________
DB2 v9.5 ESE on AIX v6.1/ v9./10 on z/OS
Reply With Quote
  #12 (permalink)  
Old 02-23-10, 12:31
qxz qxz is offline
Registered User
 
Join Date: Apr 2002
Posts: 84
Thanks for all the help.

What should I do if there is some condition, for example, to get the number of orders of a particular product. How to optimize a query like:
> select count(*) from Order_Table where product_id = 'abc'?


Quote:
Originally Posted by MarkhamDBA View Post
we have one of those - instead of using identity col or a sequence, they created a trigger which finds max(col), adds 1 and inserts it into the table. performance is awful. we are going to change it to identitly column as soon as we can.
Reply With Quote
  #13 (permalink)  
Old 02-24-10, 09:44
dav1mo dav1mo is offline
Registered User
 
Join Date: Dec 2007
Location: Richmond, VA
Posts: 782
put an index on product_id
Reply With Quote
  #14 (permalink)  
Old 02-24-10, 14:58
MarkhamDBA MarkhamDBA is offline
Registered User
 
Join Date: Dec 2008
Location: Toronto, Canada
Posts: 381
BTW if you insist on using '1+Select count (*)' to get a value for next order_no, I think it's better change it to 'max(order_no)' or you are skipping numbers because your count(*) counts NULL values too. For example, if you have 100 records and 10 of them are NULLs, your next order_no will be 101 (not 91) though your max order_no might be =90.
__________________
DB2 v9.5 ESE on AIX v6.1/ v9./10 on z/OS
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On