How can I implement a reflexive primary/foreign key relationship in Access? - ms-access-2010

MS Office 265 ProPlus, Access 2007 - 2016
I'm a novice with this.
I have a table called pedigree. I has 3 columns...
Name (text)
ID (auto increment integer, primary key)
Parent_ID (integer)
I want to implement a constraint which will require that the "parent_ID" value of each record exists as the ID value of some other record i the same table (a reflexive primary/foreign key setup).
In Access, I went to the "Database Tool" tab, then "Relationships", then opened the table up twice and tied that ID column of one to the "Parent_ID" of the other. It didn't complain, saved out OK. When I run it, it doesn't seem to work. I can put records in the table with Parent_ID values outside of the available ID value pool.
Any clues?
Also, if there's a different/better way to do this, I'm all ears. I read about the "Database Tools" -> "Relationships" approach on the web somewhere but am open to anything that might work.

And the solution for me (the novice) was...
Set the "Enforce Referrential Integrity" of the relationship.
Thanks Gustav for the hint !

Related

Lazarus fails to generate proper InsertSQL, how to remedy?

I'm using Lazarus and trying to insert payment records into a SQLite database, but apparently InsertSQL isn't autogenerating the correct INSERT statement, and I have discovered that I can't simply assign parameters to .InsertSQL by using .ParamByName like I can to the .SQL property.
My database has tables of Customers and Payments. The Payments table is as follows:
Pay_Key: Primary key, Integer, Unique, Not NULL. Identifies a single payment row in the table.
Pay_Customer: Integer, Not NULL. Foreign-key linked to an integer-type Not NULL primary key in my Customers table.
Pay_Sum: Integer. (Yes, I'm storing the payment sum as integer, but this isn't really important here.)
I'm using SELECT * FROM Payments WHERE Pay_Customer=:CustomerKey in my SQLQuery.SQL, and assigning :CustomerKey each time programmatically via SQLQuery.ParamByName('CustomerKey').Text. This lets me navigate existing records nicely in a DBGrid, but when I try to insert a new payment, the operation fails on the "Pay_Customer Not NULL" condition. Apparently Lazarus doesn't know what value to use in the Pay_Customer field, since I passed it programmatically.
Is there a way to remedy this? I can write my own InsertSQL if need be, I just don't understand how I can pass this customer parameter to it. I would very much like to use InsertSQL/UpdateSQL/DeleteSQL, since they would make it easy to use stock DBGrid/DBNavigator components and logic for what I'm doing.
Thanks for any suggestions, and sorry for being so verbose about my question.
-Sam
Edit: I'm using Lazarus 1.6 (FPC 3.0.0). I have enabled foreign keys in SQLite in SQLite3Connection.Params (foreign_keys=on)

What methods are available to monitor SQL database records?

I would like to monitor 10 tables with 1000 records per table. I need to know when a record, and which record changed.
I have looked into SQL Dependencies, however it appears that SQL Dependencies would only be able to tell me that the table changed, and not which record changed. I would then have to compare all the records in the table to find the modified record. I suspect this would be a problem for me as the records constantly change.
I have also looked into SQL Trigger's, however I am not sure if triggers would work for monitoring which record changed.
Another thought I had, is to create a "Monitoring" table which would have records added to it via the application code whenever a record is modified.
Do you know of any other methods?
EDIT:
I am using SQL Server 2008
I have looked into Change Data Capture which is available in SQL 2008 and suggested by Martin Smith. Change Data Capture appears to be a robust, easy to implement and very attractive solution. I am going to roll CDC on my database.
You can add triggers and have them add rows to an audit table. They can audit the primary key of the rows that changed, and even additional information about the changes. For instance, in the case of an UPDATE, they can record the columns that changed.
Before you write/implement your own take a look at AutoAudit :
AutoAudit is a SQL Server (2005, 2008) Code-Gen utility that creates
Audit Trail Triggers with:
Created, CreatedBy, Modified, ModifiedBy, and RowVersion (incrementing INT) columns to table
Insert event logged to Audit table
Updates old and new values logged to Audit table
Delete logs all final values to the Audit table
view to reconstruct deleted rows
UDF to reconstruct Row History
Schema Audit Trigger to track schema changes
Re-code-gens triggers when Alter Table changes the table
What version and edition of SQL Server? Is Change Data Capture available? – Martin Smith
I am using SQL 2008 which supports Change Data Capture. Change Data Capture is a very robust method for tracking data changes as I would like to. Thanks for the answer.
Here's an idea.You can have a flag on each table that every time a record is created or updated is filled with current datetime. Then when you notice that a record has changed set its flag to null again.Thus unchanged records have null in their flag field and you can query not null values to see which record has changed/created and when (and set their flags to null again) .

How to update a aprimary key field with linq to SQL?

I have tbl_names with following fields:
Id int
Name nvarchar(10)
family nvarchar(20)
Id Name Family
1 John Smith
and suppose Id and name are primary key together(compound primary key).
and I want to update name field according to the value of Id field.
DataclassesContext dac=new DataClassesContext();
var query=from record in Dac.tbl_name where record.id=1 select record;
query.name="Raymond";
Dac.Submitchanges();
but I encounter following error:
Value of member 'co_Workshop' of an object of type 'Tbl_Workshop' changed.
A member defining the identity of the object cannot be changed.
Consider adding a new object with new identity and deleting the existing one instead.
Is it because of name field is primary key? why can't I update a primary key field using linq?
I am not sure that you should find a way around this. I cannot imagine why it would be a good idea to change a value in a PK. The entire nature of a PK is that it is a stable identifier of the row.
In your case, you should drop and recreate the PK to be just the "Id" field and then if you need to improve performance on queries filtering on "name" then just add an Index on the "name" field. The fact that you only use the "Id" field to find the record supports this idea.
EDIT:
I answered before there were comments to the Question. Now that I see the comment from the OP about "it is an old database and can't change it's structure", I would say that if there are no FKs pointing to this PK then this should be a fairly straight-forward change (to drop and recreate the PK with just the "Id" field as I mentioned above). If there are FKs pointing to it then an option (though not a great option and it might not work on all RDBMS's) is to:
Drop the FKs
Drop the PK
Create the new PK on just the "Id" field
Create a UNIQUE INDEX on "Id" and "Name"
Recreate the FK's to point to the UNIQUE INDEX
This will work on Microsoft SQL Server and as much as I dislike the idea of a FK pointing to a UNIQUE INDEX, it should allow for the same structure that you have now plus LINQ will just see the single field PK on "Id" and allow for the update.
Where possible, a workaround is to delete the record whose primary key value needs updating and create a new record in its place.
It looks like there are ways around it, like I mentioned above. Linq won't let you change the primary key.
http://social.msdn.microsoft.com/Forums/en/linqprojectgeneral/thread/64064c2d-1484-4a00-a2c4-764bcb6b774a
Had the same problem. For legacy reasons, I couldn't remove the column I needed to update from being part of the primary key.
A simple solution was to not use Linq in this case, but use T_SQL and do a simple update.
update tbl_name set name = 'Raymond' where id = 1

How to create a primary key as A1/D-M/100000 in SQL Server 2005?

How to create a primary key as A1/D-M/100000 in SQL Server 2005 in Visual Studio 2008 ?
Use varchar(20) as column type and generate the primary key value from the code.
Your request is not possible in SQL Server as requested, which makes me want to tell you to do some more reading.
However, you can achieve something similar by creating a primary key in Visual Basic, and storing that value in a char or varchar field in SQL, as suggested by Adrian Godong's answer.
That said, what I would do if this were my database, is create a normal PK using int or bigint (depending on how many rows I'm planning to store), and using a second column as char or varchar, with an appropriate index, to store the Ax/D-M/xxxxxx values.
What you are wanting to do is mix business rules with SQL Server's database rules, and that's a very bad idea. SQL does not care what your data looks like, so you should not force it to do so. Your business rules may change down the line, and this would be much easier to accommodate if you do a proper PK to start with, that does not rely on some arbitrary naming convention.
What parts of that key are fixed, which change from row to row??
E.g. where does the "A1" or the "D-M" come from? Are they the same for all rows? Do they change from row to row??
If those parts are fixed, and only the big number in the middle needs to change, you could:
define a column of type ID INT IDENTITY(100000,1) for the number
define a computed column like this:
ALTER TABLE dbo.YourTable
ADD YourPKField AS 'A1/D-M/' + CAST(ID AS VARCHAR(6)) PERSISTED
In that way, SQL Server would auto-increment your ID field, and YourPKField would contain the values:
A1/D-M/100000
A1/D-M/100001
A1/D-M/100002
A1/D-M/100003
....
and so on - automatically, without you doing anything more.
Use an INT IDENTITY(100000,1) as your Primary key.
Add the calculated (displayed) key wherever you need it (queries...). It's decoration, and as such, it's part of the front-end, not of your data.

insert data from a asp.net form to a sql database with foreign key constraints

i have two tables
asset employee
assetid-pk empid-pk
empid-fk
now, i have a form to populate the asset table but it cant because of the foreign key constraint..
what to do?
thx
Tk
Foreign keys are created for a good reason - to prevent orphan rows at a minimum. Create the corresponding parent and then use the appropriate value as the foreign key value on the child table.
You should think about this update as a series of SQL statements, not just one statement. You'll process the statements in order of dependency, see example.
Asset
PK AssetID
AssetName
FK EmployeeID
etc...
Employee
PK EmployeeID
EmployeeName
etc...
If you want to "add" a new asset, you'll first need to know which employee it will be assigned to. If it will be assigned to a new employee, you'll need to add them first.
Here is an example of adding a asset named 'BOOK' for a new employee named 'Zach'.
DECLARE #EmployeeFK AS INT;
INSERT (EmployeeName) VALUES ('Zach') INTO EMPLOYEE;
SELECT #EmployeeFK = ##IDENTITY;
INSERT (AssetName, EmployeeID) VALUES ('BOOK',#EmployeeFK) INTO ASSET;
The important thing to notice above, is that we grab the new identity (aka: EmployeeID) assigned to 'Zach', so we can use it when we add the new asset.
If I understand you correctly, are you trying to build the data graph locally before persisting to the data? That is, create the parent and child records within the application and persist it all at once?
There are a couple approaches to this. One approach people take is to use GUIDs as the unique identifiers for the data. That way you don't need to get the next ID from the database, you can just create the graph locally and persist the whole thing. There's been a debate on this approach between software and database for a long time, because while it makes a lot of sense in many ways (hit the database less often, maintain relationships before persisting, uniquely identify data across systems) it turns out to be a significant resource hit on the database.
Another approach is to use an ORM that will handle the persistence mapping for you. Something like NHibernate, for example. You would create your parent object and the child objects would just be properties on that. They wouldn't have any concept of foreign keys and IDs and such, they'd just be objects in code related by being set as properties on each other (such as a "blog post" object with a generic collection of "comment" objects, etc.). This graph would be handed off to the ORM which would use its knowledge of the mapping between the objects and the persistence to send it off to the database in the correct order, perhaps giving back the same object but with ID numbers populated.
Or is this not what you're asking? It's a little unclear, to be honest.

Resources