I am getting persistent but intermittent "Violation of PRIMARY KEY constraint" Errors - sql-server-2008

I am the person in my company who tries to solve coldfusion errors and bugs. We get daily emails with full details of coldfusion errors etc, as well we store this information in our database.
And for a few different applications in ColdFusion, they seem to sporadically generated "Violation of PRIMARY KEY constraint" errors.
In the code we always check for the existence of a row in the database before we try to do an insert, and it still generate's that error.
So my thinking is, either we need to a cftransaction around these each of the check, insert or update blocks. But I am not sure this will truly solve the problem.
These are coded in standard coldfusion style/framework. Here is an example in pseudo-code.
cfquery name="check_sometable" datasource="#dsn#"
select id
from sometable
/cfquery
if check_sometable.recordcount gt 0
-do insert
else
-do update
/endif
So why would this intermittently, cause primary key violations?
Is this a sql server problem, are we missing a configuration option?
Are we getting all of this because we are not on the latest hotfixed version of coldfusion 8 standard?
Do we need to upgrade our jdbc/odbc drivers?
Thank You.

Sounds like race conditions to me. Two connections check for the next available id at the same time, get the same one and then the insert fails on the second one. Why are you not using an identity field to create the PK if it is a surrogate key?
If you have a PK that is a natural key, then the violation is a good thing, you have two users trying to insert the same record which you do not want. I would try to fail it gracefully though, with an error that says someone else has created the same record. And then ask if they want to update it after loading the new values to their screen. I'm not sure I would want it to set up so that the data is automatically updated by the second person without them seeing what the first person put into the database.
Further this might be an indication that your natural key is not as unique as you think it is. Not sure what this application does, but how likely is it that two people would want to be working with the same data at a the same time? So if your natural key were something like company name, be aware that they are not guaranteed to be unique and you might have users overwriting good data for one company with data for another company already. I've found in life there are truly very few really unique, never changing natural keys. So if your natural key really isn't unique, you may already have bad data and the PK violations are just a symptom of a differnt problem not the real problem.

Related

entering an entire record in a table automatically updates the respective fields in other table

I have got two tables...Table 1 is having 4 columns as : 'p_id' , 'email' , 'password', 'contact_number'.......'p_id' is the PRIMARY KEY of the Table 1.
Table 2 has got 5 columns, they are : 'p_id' , 'password' ,'email' , 'contact_number' , 'cust_id' ...................here 'p_id' is serving as the FOREIGN KEY from Table 1.
Now my question is that if we insert the three fields in Table 1 then is there any way that the "respective" same fields in the Table 2 also gets updated with the same values from Table 1?
I'm new to this forum so apologies if i didn't match the question asking etiquette...:).
I avoid triggers because they cause additional maintenance considerations. http://www.ducea.com/2007/07/25/dumping-mysql-stored-procedures-functions-and-triggers/ for instance. Of course it can be done. But I suspect the authors of SQL standards intended foreign keys to be used to solve this problem.
You can add FOREIGN KEY constraints with multiple indexes, so if I'm not mistaken, you can use such syntax so that when the data is changed in the one table, it will also be changed in the other.
http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION
That having been said, I do recommend looking at https://en.wikipedia.org/wiki/Third_normal_form - you don't need or want to store the same information in more than one place. Instead, as others have suggested, http://dev.mysql.com/doc/refman/5.7/en/join.html - use JOIN to combine the tables when you select from them.
Thank you for providing the clarification about your use case:
actually the concept is that there would be a registration panel ..the
user will enter his data ...these will get stored in the second
table....now when he/she login this data will be matched and his/her
details from the database will be loaded
from what you describe, you don't seem to need 2 tables at all. You store their values, they supply them, and you check to see if they match. Why do you need the other table for that? Simply execute a WHERE clause to check whether the values they provided exist in the database. Where does the second table even come in?
I sincerely hope you consider this advice: Authentication is about the worst thing to build yourself, so much more so if you're learning. You might want to post a question to the appropriate programming community regarding the use of a pre-built auth layer that would meet your needs. It would probably store the data in a database much like yours, but would include valuable sercurity considerations to protect not just you, but also your users.
For instance, storing a plain text password in the database is a terrible practice. If your site suffered a data access breach such as https://en.wikipedia.org/wiki/SQL_injection your users' emails and passwords would be exposed, and in that case the attacker has a valuable login set that is probably used on some other website ( of course you should never reuse your passwords, but obviously lots of folks do ). Now you've exposed your users' accounts all across the internet.
https://en.wikipedia.org/wiki/Cryptographic_hash_function#Password_verification explains how usually only a one way hash of the password ( eg sha256 ) is required to authorize the user. If you want to be really cool, you can even hash before you send the data to the server: https://softwareengineering.stackexchange.com/questions/76939/why-almost-no-webpages-hash-passwords-in-the-client-before-submitting-and-hashi . This works because a good hash can't be reversed ( you'd have to brute force, a computationally untenable operation) but always yield the same results with the same input.
If you're getting started programming, why not leave the auth to an open source drop in solution and focus on the guts of your app logic? It's what the pros do.
Classic denormalization problem. The correct solution is to redesign your data. The real problem here is that the two tables aren't normalized, so you have repeated data. This is a violation of 3NF, and it is the only reason your question even exists. Even if you solve this part of it with some dreadful hack, you will then have the further problem of having to update both tables at the same time, and what to do (which is right?) if they ever get out of sync.
I can't see a single reason why you even need two tables, but if you do the second one should consist only of a foreign key into the first one, and then columns for all the data that isn't in the first one. In this case, everything starting from cust_id, ...
Use an AFTER INSERT trigger:
delimiter //
CREATE TRIGGER Table1_AI
AFTER INSERT ON Table1
FOR EACH ROW
BEGIN
UPDATE Table2 t2
SET t2.password = NEW.password,
t2.email = NEW.email,
t2.contact_number = NEW.contact_number
WHERE t2.p_id = NEW.p_id;
END;//
delimiter ;
This presumes that the row to be modified already exists in Table2. If it might not you might want to use an INSERT...ON DUPLICATE KEY UPDATE... statement in the body of the trigger.
Best of luck.

MySQL: Insert a new row at a specific primary key, or alternately, bump all subsequent rows down?

I am creating two tables in a database in MySQL just so I can play around with SQL and learn more, as I am a novice. I have read several questions on Stack relating to inserting a new row, and updating an existing row. My question is a little different, hopefully it won't be considered a dupe as none of the other answers I read gave me the full explanation I need because I think it's the auto-increment part that's confusing me. I don't think I can just go in and assign a new value for the primary keys in one of the tables with auto-increment set up, can I?
I have two tables: english_words and spanish_words. Their primary keys are respectively eng_id and span_id, and are set up to auto-increment. My hope had been to practice SQL and eventually get things set up enough so that I can practice my joins later on. For now, in english_words, I entered a duplicate row by mistake, with the ID 7. I deleted that row, and of course it now goes "6...8..." ..... and when I created my spanish_words table, I forgot all about the missing row 7. I'd hoped to keep everything very simple and aligned between the two tables until I'm ready for more complex endeavors later. Is there a way I can either:
Bump row 7 (and all subsequent rows) down by one in my spanish_words (so 7 becomes 8, 8 becomes 9, etc)
OR
Pull up everything after row 6 in english_words?
OR
Is there a better solution than either of those that you could suggest?
It's possible there's not a way. Originally I'd thought of trying to UPDATE the row 7 data in english_words or maybe insert a new row, but in my research I found an answer on Stack that said you can't insert data into a specific row in the table...and then I realized that's not going to fix anything anyway.
Do those of you more experienced with SQL have any ideas? (Aside from not making such silly mistakes anyway).
Additionally, I'm open to scrapping my tables and starting again, if there's a best-practice that I'm missing. Would setting up a foreign key to correspond between the two tables be a way to fix this? I'm pretty sure you have to do that anyway to perform the joins, but I was going to cross that bridge when I get there. What is best practice amongst database admins - set up foreign keys early on, or later when you need them?
Thanks in advance for your guidance.
A better way to set this up is to create a relation table:
CREATE TABLE translation (
eng_id int,
span_id int,
FOREIGN KEY (eng_id) REFERENCES english_words (eng_id),
FOREIGN KEY (span_id) REFERENCES spanish_words (span_id)
)
This is better than using a foreign key in the original tables, because you can't have bidirection foreign keys (you have to create the referenced row before the referencing row, so whichever table you insert into first can't have a foreign key pointing to the other one).

DB design for M:N table with time interval

i would like to ask you a design question:
I am designing a table that makes me scratch my head, not sure what the best approach is, i feel like i am missing something:
There are two tables A and B and one M:N relationship table between them. The relationship table has right now these values:
A.ID, B.ID, From, To
Bussiness requirements:
At any time, A:B relation ship can be only 1:1
A:B can repeat in time as defined by From and To datetime values, which specify an interval
example: Car/Driver.
Any car can have only 1 Driver at any time
Any Driver can drive only 1 car at any time (this is NOT topgear, ok? :) )
Driver can change the car after some time, and can return to the same car
Now, i am not sure:
- what PK should i go with? A,B is not enough, adding From and To doesnt feel right, maybe an autoincrement PK?
-any way to enforce the bussiness requirements by DB design?
-for business reason, i would prefer it not to be in a historical table. Why? Well, let's assume the car is rented and i want to know, given a date, who had what car rented at that date. Splitting it into historical table would require more joinst :(
I feel like i am missing something, some kind of general patter ... or i dont know....
Thankful for any help, so thank you :)
I don't think you are actually missing anything. I think you've got a handle on what the problem is.
I've read a couple of articles about how to handle "temporal" data in a relational database.
Bottom line consensus is that the traditional relational model doesn't have any builtin mechanism for supporting temporal data.
There are several approaches, some better suited to particular requirements than others, but all of the approaches feel like they are "duct taped" on.
(I was going to say "bolted on", but I thought at tip of the hat to Red Green was in order: "... the handyman's secret weapon, duct tape", and "if the women don't find you handsome, they should at least find in you handy.")
As far as a PRIMARY KEY or UNIQUE KEY for the table, you could use the combination of (a_id, b_id, from). That would give the row a unique identifier.
But, that doesn't do anything to prevent overlapping "time" ranges.
There is no declarative constraint for a MySQL table that prevents "overlapping" datetime ranges that are stored as "start","end" or "start","duration", etc. (At least, in the general case. If you had very well defined ranges, and triggers that rounded the from to an even four hour boundary, and a duration to exactly four hours, you could use a UNIQUE constraint. In the more general case, for any ol' values of from and to, the UNIQUE constraint does not work for us.
A CHECK constraint is insufficient (since you would need to look at other rows), and even if it were possible, MySQL doesn't actually enforce check constraints.
The only way (I know of) to get the database to enforce such a constraint would be a TRIGGER that looks for the existence of another row for which the affected (inserted/updated) row would conflict.
You'd need both a BEFORE INSERT trigger and a BEFORE UPDATE trigger. The trigger would need to query the table, to check for the existence of a row that "overlaps" the new/modified row
SELECT 1
FROM mytable t
WHERE t.a_id = NEW.a_id
AND t.b_id = NEW.b_id
AND t.from <> OLD.from
AND < (t.from, t.to) overlaps (NEW.from,NEW.to) >
Obviously, that last line is pseudocode for the actual syntax that would be required.
The line before that would only be needed in the BEFORE UPDATE trigger, so we don't find (as a "match") the row being updated. The actual check there would really depend on the selection of the PRIMARY KEY (or UNIQUE KEY)(s).
With MySQL 5.5, we can use the SIGNAL statement to return an error, if we find the new/updated row would violate the constraint. With previous versions of MySQL, we can "throw" an error by doing something that causes an actual error to occur, such as running a query against a table name that we know does not exist.
And finally, this type of functionality doesn't necessarily have to be implemented in a database trigger; this could be handled on the client side.
How about three tables:
TCar, TDriver, TLog
TCar
pkCarID
fkDriverID
name
A unique index on driver ensures a driver is only ever in one car. Turning the foreign key
fkDriverID into a 1:1 relation ship.
TDriver
pkDriverID
name
TLog
pkLogID (surrogate pk)
fkCarID
fkDriverID
from
to
With 2 joins you will get any information you describe. if you just need to find Car data by driverID or driver data by cardid you can do it with one join.
thank you everyone for you input, so far i am thinking about this approach, would be thankful for any criticism/pointing out flaws:
Tables (pseudoSQLcode):
Car (ID pk auto_increment, name)
Driver(ID pk auto_increment, name)
Assignment (CarID unique,DriverID unique,from Datetime), composite PK (CarID,DriverID)
AssignmentHistory (CarID unique,DriverID unique,from Datetime,to Datetime) no pk
of course, CarID is a FK to Car(ID) and DriverID is a FK to Driver(ID)
the next stage are two triggers (and boy oh boy, i hope this can be done in mysql (works on MSSSQL, but i dont have a mysql db handy right now to test):
!!! Warning, MSSQL for now
create trigger Assignment _Update on Assignment instead of update as
delete Assignment
from Assignment
join inserted
on ( inserted.CarID= Assignment .CarID
or inserted.DriverID= Assignment .DriverID)
and ( inserted.CarID<> omem.CarID or inserted.DriverID<> omem.DriverID)
insert into Assignment
select * from inserted;
create trigger Assignment _Insert on Assignment after delete as
insert into Assignment_History
select CarID,DriverID,from,NOW() from deleted;
i tested it a bit and it seems for each bussiness case it does what i need it to do

How to deal with duplicates in database?

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!

handling mysql constraint errors

I tried searching for a solution in this website but I can't seem to find any.
I needed to find a way to know which field in my table is causing the constraint error.. In my table, say members table two fields (username,email) are unique keys and defined as unique keys apart from my primary key (memberid). When i add data to this table for a similar user and/or email address this error occurs:
"duplicate entry 'myemail#mail.com' for key2"
i want to tell the user which field is causing duplicate entry so as to say "that email is already registered"
I cannot seem to find a mysql function to loop through error keys upon insert...
On my sites, I actually check the unique fields myself with Select 1 from tab where field = 'value' limit 1; just so that I can give nice error messages instead of encountering an exception coming back from my insert statement.
i guess naming constraint fields is not yet a feature in mysql. hope they consider this as this is very useful and saves a lot of code times and lines.