in my application i want to add to every record in a database table a code which must be unique and randomly generated (so unpredictable for users). I assume that generating this by code (java ee) is a bad idea because it will need to request frequently the database management system (MySQL) to check for the unicity.
Can someone help me to generate this code by SQL like for a variable char (varchar) with a size n.
Thanks for your help.
UUID()
Will this work? Of course you would have to store the value of the UUID as your VARCHAR if that is what you wanted rather than the UUID type.
MySQL can verify the uniqueness of a value if you assign a Unique Index to that field. For instance, if you have a table with the columns name, age, code, and you can set a unique key to code and it will make sure that code is never duplicated.
That way you can generate a unique string/number/whatever in whatever language you want (e.g. Java EE) and then insert that string into the table. MySQL will reject an insertion if the key is already being used.
Here's a link to MySQL documentation on adding keys to the table: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
Hope that helps.
Good luck.
Related
I've been reading some articles about usage of composite keys in MySql and found that a composite key can't own a auto_increment id column. However, I'm interested in using a similar feature. Let's explain it:
Using MariaDB 10 (InnoDB) and Hibernate 3.6.9
I want to do some of my application table fields translatable. I have thought an only table for translations should be enough. This table has a composite key which has an int value as a key for the translation and also the locale value for the concrete text. The same id and locale values can't place as entries.
So that's how the model should look like:
I don't want the translations to be loaded with each of the random entities as a Collection, I'm thinking about a method like String translationFor(Integer id, Locale loc) could do it for my current locale. However, when I save some translation Set I want to assign them the same id. Let's take this case:
Spanish: Cuchara
English: Spoon
The table should look as:
id locale translation
1 es Cuchara
1 en Spoon
But I can't tell MySql to have a composite id with auto_increment column. So, I consider I should assign it manually, performing these steps:
Build the Translation entities with the locale values
Begin a transaction in Hibernate session
Retrieve the last id value in the translations table
Assign it manually to the entities
Save them
Commit the transaction
Is it the most proper way? Am I doing it atomically?
I assume you are planning on having multiple tables needing the translation of 'spoon'? If so, let me move your focus away from id.
The translation table needs PRIMARY KEY(code, locale) where code is what you have as some_translatable_value in `random_table_1.
code could be the string (perhaps abbreviated) in your favorite language. Note that if you later change the phrasing of the text (to "silver spoon"), do not go back and change code; it can stay the same ("spoon").
I do not know whether you can achieve this in Hibernate; I am not fluent in that. (I tend to avoid 3rd party packages; they tend to get int the way.) If Hibernate forces you to have an AUTO_INCREMENT id on each table, so be it. It will be a harmless waste. You should then declare the pair (code, locale) as unique (in order to get the desired index).
i want to generate a id number for my user table.
id number is unique index.
here my trigger
USE `schema_epolling`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` TRIGGER `tbl_user_BINS` BEFORE INSERT ON `tbl_user`
FOR EACH ROW
BEGIN
SET NEW.id_number = CONCAT(DATE_FORMAT(NOW(),'%y'),LPAD((SELECT auto_increment FROM
information_schema.tables WHERE table_schema = 'schema_epolling' AND table_name =
'tbl_user'),6,0));
END
it works if i insert one by one .. or may 5 rows at a time.
but if i insert a bulk rows.. an error occured.
id number
heres the code i use for inserting bulk rows from another schema/table:
INSERT INTO schema_epolling.tbl_user (last_name, first_name)
SELECT last_name, first_name
FROM schema_nc.tbl_person
heres the error:
Error Code: 1062. Duplicate entry '14000004' for key 'id_number_UNIQUE'
Error Code: 1062. Duplicate entry '14000011' for key 'id_number_UNIQUE'
Error Code: 1062. Duplicate entry '14000018' for key 'id_number_UNIQUE'
Error Code: 1062. Duplicate entry '14000025' for key 'id_number_UNIQUE'
Error Code: 1062. Duplicate entry '14000032' for key 'id_number_UNIQUE'
if i use uuid() function it works fine. but i dont want uuid() its too long.
You don't want to generate id values that way.
The auto-increment value for the current INSERT is not generated yet at the time the BEFORE INSERT trigger executes.
Even if it were, the INFORMATION_SCHEMA would contain the maximum auto-increment value generate by any thread, not just the thread executing the trigger. So you would have a race condition that would easily conflict with other concurrent inserts and get the wrong value.
Also, querying INFORMATION_SCHEMA on every INSERT is likely to be a bottleneck for your performance.
In this case, to get the auto-increment value formatted with the two-digit year number prepended, you could advance the table's auto-increment value up to %y million, and then when we reach January 1 2015 you would ALTER TABLE to advance it again.
Re your comments:
The answer I gave above applies to how MySQL's auto-increment works. If you don't rely on auto-increment, you can generate the values by some other means.
Incrementing another one-row table as #Vatev suggests (though this creates a relatively long-lived lock on that table, which could be a bottleneck for your inserts).
Generating values in your application, based on an central, atomic id-generator like memcached. See other ideas here: Generate unique IDs in a distributed environment
Using UUID(). Yes, sorry, it's 32 characters long. Don't truncate it or you will use uniqueness.
But combining triggers with auto-increment in the way you show simply won't work.
I'd like to add my two cents to expound on Bill Karwin's point.
It's better that you don't generate a Unique ID by attempting to manually cobble one together.
The fact that your school produces an ID in that way does not mean that's the best way to do it (assuming that is what they are using that generated value for which I can't know without more information).
Your database work will be simpler and less error prone if you accept that the purpose for an ID field (or key) is to guarantee uniqueness in each row of data, not as a reference point to store certain pieces of human readable data in a central spot.
This type of a ID/key is known as a surrogate key.
If you'd like to read more about them here's a good article: http://en.wikipedia.org/wiki/Surrogate_key
It's common for a surrogate key to also be the primary key of a table, (and when it's used in this way it can greatly simplify creating relationships between tables).
If you would like to add a secondary column that concatenates date values and other information because that's valuable for an application you are writing, or any other purpose you see fit, then create that as a separate column in your table.
Thinking of an ID column/key in this, fire & forget, way may simplify the concept enough that you may experience a number of benefits in your database creation efforts.
As an example, should you require uniqueness between un-associated databases, you will more easily be able to stomach the use of a UUID.
(Because you'll know it's purpose is merely to ensure uniqueness NOT to be useful to you in any other way.)
Additionally, as you've found, taking the responsibility on yourself, instead of relying on the database, to produce a unique value adds time consuming complexity that can otherwise be avoided.
Hope this helps.
I am new in microsoft access. I was just wondering on how can I use create a custom primary key? for example abc-123 format?
It depends on how you want the abc-123 values to be created.
If you want to create them by yourself in your code, just create a Text column and use that as your primary key.
If you want Access to create these values...that's not really possible. The only thing that Access is able to auto-generate are increasing numerical values (data type AutoNumber).
So the best thing you can do is to use an AutoNumber internally as the actual primary key, and create the abc-123 value out of that, just for displaying.
Here are some examples how to do this, from previous similar questions that I answered in the past:
access 2003 text display leading zero
Automatically generate numbers
Disclaimer: I don't know if a similar approach would work in your case.
If not, you need to give more information how exactly you want your numbers to be created:
do you want the number to increase?
do you want the letters to change/"increase"/always stay the same?
Actually, you could create a table trigger if using 2010 or later. The table trigger could take some field (where you get the abc from) and then some other field (seq num) and then add + 1 to the value.
The "air" code would look like this:
The beauty of the table trigger is it runs at table (data engine) level, and thus if you open the database with ODBC, VB.net, FoxPro, Access etc. then the PK key will always auto generate for you.
In a program, should we use try catch to check insertion of duplicate values into tables, or should we check if the value is already present in the table and avoid insertion?
This is easy enough to enforce with a UNIQUE constraint on the database side so that's my recommendation. I try to put as much of the data integrity into the database so that I can avoid having bad data (although sometimes unavoidable).
If this is how you already have it you might as well just catch the mysql exception for duplicate value insertion on such a table as doing the check then the insertion is more costly then having the database do one simple lookup (and possibly an insert).
Depends upon whether you are inserting one, or a million, as well as whether the duplicate is the primary key.
If its the primary key, read: http://database-programmer.blogspot.com/2009/06/approaches-to-upsert.html
An UPSERT or ON DUPLICATE KEY... The idea behind an UPSERT is simple.
The client issues an INSERT command. If a row already exists with the
given primary key, then instead of throwing a key violation error, it
takes the non-key values and updates the row.
This is one of those strange (and very unusual) cases where MySQL
actually supports something you will not find in all of the other more
mature databases. So if you are using MySQL, you do not need to do
anything special to make an UPSERT. You just add the term "ON
DUPLICATE KEY UPDATE" to the INSERT statement:
If it's not the primary key, and you are inserting just one row, then you can still make sure this doesn't cause a failure.
For your actual question, I don't really like the idea of using try/catch for program flow, but really, you have to evaluate readability and user experience (in this case performance), and pick what you think is the best of mix of the two.
You can add a UNIQUE constraint to your table.. Something like
CREATE TABLE IF NOT EXISTS login
(
loginid SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
loginname CHAR(20) NOT NULL,
UNIQUE (loginname)
);
This will ensure no two login names are the same.
you can Create a Unique Composite Key
ALTER TABLE `TableName` ADD UNIQUE KEY (KeyOne, KeyTwo, ...);
you just need to create a unique key in your table so that it will not permit to add the same value again.
You should try inserting the value and catch the exception. In a busy system, if you check for the existience of a value it might get inserted between the time you check and the time you insert it.
Let the database do it's job, let the database check for the duplicate entry.
A database is a computerized representation of a set of business rules and a DBMS is used to enforce these business rules as constraints. Neither can verify a proposition in the database is true in the real world. For example, if the model in question is the employees of an enterprise and the Employees table contains two people named 'Jimmy Barnes' DBMS (nor the database) cannot know whether one is a duplicate, whether either are real people, etc. A trusted source is required to determine existence and identity. In the above example, the enterprise's personnel department is responsible for checking public records, perusing references, ensuring the person is not already on the payroll, etc then allocating an unique employee reference number that can be used as a key. This is why we look for industry-standard identifiers with a trusted source: ISBN for books, VIN for cars, ISO 4217 for currencies, ISO 3166 for countries, etc.
I think it is better to check if the value already exists and avoid the insertion. The check for duplicate values can be done in the procedure that saves the data (using exists if your database is an SQL database).
If a duplicate exists you avoid the insertion and can return a value to your app indicating so and then show a message accordingly.
For example, a piece of SQL code could be something like this:
select #ret_val = 0
If exists (select * from employee where last_name = #param_ln and first_name = #param_fn)
select #ret_val = -1
Else
-- your insert statement here
Select #ret_val
Your condition for duplicate values will depend on what you define as a duplicate record. In your application you would use the return value to know if the data was a duplicate. Good luck!
I would like to restrict a column value in a SQL table. For example, the column values can only be "car" or "bike" or "van". My question is how do you achieve this in SQL, and is it a good idea to do this on the DB side or should I let the application restrict the input.
I also have the intention to add or remove more values in the future, for example, "truck".
The type of Databases I am using are SQLite and MySQL.
Add a new table containing these means of transport, and make your column a foreign key to that table. New means of transport can be added to the table in future, and your column definition remains the same.
With this construction, I would definitively choose to regulate this at the DB level, rather than that of the application.
For MySQL, you can use the ENUM data type.
column_name ENUM('small', 'medium', 'large')
See MySQL Reference: The ENUM Type
To add to this, I find it's always better to restrict on the DB side AND on the app side. An Enum plus a Select box and you're covered.
Yes, it is recommended to add check constraints. Check constraints are used to ensure the validity of data in a database and to provide data integrity. If they are used at the database level, applications that use the database will not be able to add invalid data or modify valid data so the data becomes invalid, even if the application itself accepts invalid data.
In SQLite:
create table MyTable
(
name string check(name = "car" or name = "bike" or name = "van")
);
In MySQL:
create table MyTable
(
name ENUM('car', 'bike', 'van')
);
You would use a check constraint. In SQL Server it works like this
ALTER TABLE Vehicles
ADD CONSTRAINT chkVehicleType CHECK (VehicleType in ('car','bike','van'));
I'm not sure if this is ANSI standard but I'm certain that MySQL has a similar construct.
If you want to go with DB-side validation, you can use triggers. See this for SQLite, and this detailed how-to for MySQL.
So the question is really whether you should use Database validation or not. If you have multiple clients -- whether they are different programs, or multiple users (with possibly different versions of the program) -- then going the database route is definitely best. The database is (hopefully) centralized, so you can decouple some of the details of validation. In your particular case, you can verify that the value being inserted into the column is contained in a separate table that simply lists valid values.
On the other hand, if you have little experience with databases, plan to target several different databases, and don't have the time to develop expertise, perhaps simple application level validation is the most expedient choice.
To add some beginner level context to the excellent answer of #NGLN above.
First, one needs to check the foreign key constraint is active, otherwise sqlite won't limit to the input to the column to the reference table:
PRAGMA foreign_key;
...which gives a response of 0 or 1, indicating on or off.
To set the foreign key constraint:
PRAGMA foreign_keys = ON;
This needs to be set to ensure that sqlite3 enforces the constraint.
I found it simplest to just set the primary key of the reference table to be the type. In the OP's example:
CREATE TABLE IF NOT EXISTS vehicle_types(
vehicle_type text PRIMARY KEY);
Then, one can insert 'car', 'bike' etc into the vehicle_types table (and more in the future) and reference that table in the foreign key constraint in the child table (the table in which the OP wished to reference the type of vehicle):
CREATE TABLE IF NOT EXISTS ops_original_table(
col_id integer PRIMARY KEY,
...many other columns...
vehicle_type text NOT NULL,
FOREIGN KEY (vehicle_type) REFERENCES vehicle_types(vehicle_type);
Outwith the scope of the OP's question but also take note that when setting up a foreign key constraint thought should be given to what happens to the column in child table (ops_original_table) if a parent table value (vehicle_types) is deleted or updated. See this page for info