Make a query updateable - sql

Here is my non-updateable query in MS Access 2007:
SELECT [OnlineDirectory].BC_SPEC2
FROM [OnlineDirectory] INNER JOIN Certifs_ABMS
ON [OnlineDirectory].ThisID = Certifs_ABMS.ThisID;
Both OnlineDirectory and Certifs_ABMS:
are local tables with a primary key index.
have indexes ("duplicates okay") on the field ThisID.
The query
has a recordset type of dynaset.
has no record locks.
These are both updateable:
SELECT * FROM [OnlineDirectory]
SELECT * FROM [Certifs_ABMS]
I have reviewed Allen Browne's famous list of hazards and none of them apply. UPDATE: Not true. See accepted answer.
I got excited about adding DISTINCTROW as suggested here, but no success.
How can I make this query updateable?

Both OnlineDirectory and Certifs_ABMS have indexes ("duplicates okay") on the field ThisID.
This is the problem. At least one side of the INNER JOIN needs a unique index (usually a primary key), or the relation is ambiguous.
(Allen Browne: - The fields in a JOIN are not indexed correctly: there is no primary key or unique index on the JOINed fields.)
E.g. if there are in both tables two records each with ThisID = 77. How should the records be matched?
If this is a n:m relation, you need a junction table between them.

Related

Must a natural join be on a shared primary key?

Suppose I perform A natural join B, where:
A's schema is: (aID), where (aID) is a primary key.
B's schema is: (aID,bID), where (aID, bID) is a composite primary key.
Would performing the natural join work in this case? Or is it necessary for A to have both aID and bID for this to work?
NATURAL JOIN returns rows with one copy each of the common input table column names and one copy each of the column names that are unique to an input table. It returns a table with all such rows that can be made by combining a row from each input table. That is regardless of how many common column names there are, including zero. When there are no common column names, that is a kind of CROSS JOIN aka CARTESIAN PRODUCT. When all the column names are common, that is a kind of INTERSECTION. All this is regardless of PKs, UNIQUE, FKs & other constraints.
NATURAL JOIN is important as a relational algebra operator. In SQL it can be used in a certain style of relational programming that is in a certain sense simpler than usual.
For a true relational result you would SELECT DISTINCT. Also relations have no special NULL value whereas SQL JOINs treat a NULL as not equal to a NULL; so if we treat NULL as just another value relationally then SQL will sometimes not return the true relational result. (When both arguments have a NULL for each of some shared columns and both have the same non-NULL value for each other shared column.)
A "natural" join uses the names of columns to match between tables. It uses any matching names, regardless of key definitions.
Hence,
select . . .
from a natural join b
will use AId, because that is the only column with the same name.
In my opinion, natural join is an abomination. For one thing, it ignores explicitly declared foreign key relationships. These are the "natural join" keys, regardless of their names.
Second, the join keys are not clear in the SELECT statement. This makes debugging the query much more difficult.
Third, I cannot think of a SQL construct where adding a column or removing a column from a table takes a working query and changes the number of rows in the result set.
Further, I often have common columns on my tables -- CreatedAt, CreatedOn, CreatedBy. Just the existence of these columns precludes using natural joins.

SQL One-to-one relationship join

I have 2 tables one is an extension of the other so it is currently a simple one-to-one relationship (this is likely to become one-to-many in the future). I need to join from one table to another to pull a value out of another column in the extension.
so table A contains basic details including an id and table B uses a FK reference to the Id column in table A. I need to pull out column X from table B.
To add complexity sometimes there won't be a matching entry in table B but in that case it needs to return null. Also the value of X could be null.
I know I can use a left outer join but is there a more efficient way to perform the join?
Left outer join is the way. In order to make it most efficient, make sure you index the FK column in table B. It will be super-fast with the index.
You don't need to index the primary key in table A for this query (and most databases already index primary keys anyway).
The MySQL syntax for creating the index:
CREATE INDEX `fast_lookups` ON `table_b` (`col_name`);
You can name it whatever, I picked "fast_lookups."

Unable to join 6 tables with out any primary or foreign keys - Out of memory

I have six tables, which unfortunately does not have any primary/foreign key-relations encoded. I've tried to create a view, however I am more than happy with just a table.
I've managed to join the six tables, but after returning 33.5 million rows (cleanInventtrans has 1.7 million rows and every time more tables are added, I am assuming the tables are multiplied by the combination of the previous table) I run out of memory. Now, I realize this is not the correct way of doing this, if it was I'd get a result I am assuming.
I've looked at a couple of questions online
http://www.daniweb.com/web-development/databases/ms-sql/threads/123446/problem-using-join-with-six-tables
SQL joining 6 tables
Unable to relate two MySQL tables (foreign keys)
And I've looked at
http://www.techonthenet.com/sql/joins.php
However, they assume there is a primary-foreign key relationship, my tables do not have this but there are fields which correspond, between the various tables, as seen in the SQL code below. I use these to match up the tables, but somewhere along the line, I am clearly doing it wrong.
I understand that by doing it like this I am essentially multiplying results with each table I join with. I was hoping there was a more clever/correct way of doing it which reduces the amount of results to a management size.
I am unfortunately unable to provide a create statement.
The code I am using:
SELECT dbo.AX_SALESLINE.SALESID, dbo.AX_SALESLINE.ITEMID, dbo.AX_SALESLINE.QTYORDERED, dbo.AX_SALESLINE.SALESPRICE, dbo.AX_SALESLINE.LINEPERCENT,
dbo.AX_SALESLINE.LINEAMOUNT, dbo.AX_SALESLINE.SALESQTY, dbo.AX_SALESLINE.CONFIRMEDDLV, dbo.CleanInventTrans.COSTAMOUNTPOSTED,
dbo.CleanInventTrans.DATEPHYSICAL, dbo.AX_CUSTPACKINGSLIPJOUR.DELIVERYDATE, dbo.AX_SALESTABLE.CUSTACCOUNT, dbo.AX_SALESTABLE.SALESTYPE,
dbo.AX_SALESTABLE.SALESSTATUS, dbo.AX_CUSTPACKINGSLIPJOUR.QTY, dbo.AX_PRODTABLE.PRODID
FROM dbo.AX_CUSTPACKINGSLIPJOUR INNER JOIN
dbo.AX_SALESTABLE INNER JOIN
dbo.CleanInventTrans INNER JOIN
dbo.AX_INVENTTABLE ON dbo.CleanInventTrans.ITEMID = dbo.AX_INVENTTABLE.ITEMID INNER JOIN
dbo.AX_PRODTABLE ON dbo.AX_INVENTTABLE.ITEMID = dbo.AX_PRODTABLE.ITEMID INNER JOIN
dbo.AX_SALESLINE ON dbo.AX_INVENTTABLE.ITEMID = dbo.AX_SALESLINE.ITEMID ON dbo.AX_SALESTABLE.SALESID = dbo.AX_SALESLINE.SALESID ON
dbo.AX_CUSTPACKINGSLIPJOUR.SALESID = dbo.AX_SALESLINE.SALESID
Edit:
Salesline and salestable can be related via P/F-keys, however inventtable and salesline does not have a relationship beyond having a column named itemid, which is the same in both. But these have duplicates and can not function as keys.
Edit2:
Salesline and inventtable cannot be related for some reason:
'AX_INVENTTABLE' table saved successfully
'AX_SALESLINE' table
- Unable to create relationship 'FK_AX_SALESLINE_AX_INVENTTABLE'.
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_AX_SALESLINE_AX_INVENTTABLE". The conflict occurred in database "VS1", table "dbo.AX_INVENTTABLE", column 'ITEMID'.
I've checked the itemid in inventtable, it is unique, and there are multiple of the itemid in the salesline - however not all ID's are numerical in nature, some contain letters. I am not sure if this is what is causing the problem yet.
Edit3:
Foreign-primary relation fails because there are IDs in salines which are not present in the inventtable. Very odd.
Don't bring back all of the rows from these 6 tables. If there are 1million plus rows in some of the tables at least filter on one of these tables, i.e.the CleanIventTrans table using a WHERE clause. If you're not going to add primary and foreign keys, at least add indexes to help improve performance.

How do you keep a JOIN table performant?

I'm drawing up plans for a few new features on my site, and one could be "solved" using a join table.
Example schema:
Person table
PK PersonId
Name
Age ...
PersonCheckin table
PK FK PersonId
PK FK CheckinId
Date ...
Checkin table
PK CheckinId
CheckedInto ...
A join would be run to get the check in data for a person (connected by the PersonCheckin table). Since every person could check in an unlimited number of times, the PersonCheckin table could become very large.
I'd imagine this would cause some performance issues. What are typical ways this is handled to keep performance high?
A join is considering the best performing means of connecting related tables.
But it really depends on the query, because it might not need to be a JOIN -- JOINing can inflate the record set on the parent tables side if there are more than one child record related, which means there could be a need for either GROUP BY or DISTINCT. EXISTS or IN is a better choice in such situations...
Indexes can help on the column(s) used in the JOIN criteria, on both sides of the relationship. In this example both sides are primary keys, which typically have the best index automatically created when the primary key is defined...
If you are going to execute this query very often and you want to achieve better performance just create a view on the database where you write the join query

How do I query for foreign keys that don't match their constraints?

SQL Server 2005.
I'm adding Foreign Key constraints to the database of an application that allegedly didn't need them. Naturally, the data has become unreliable and there are orphaned entries in the foreign key field.
Setup:
Two tables, TableUser and TableOrder.
TableUser has Primary Key 'UserID', and TableOrder has Foreign Key 'UserID'.
How do I find the rows where TableOrder.UserID has no matching entry in TableUser.UserID?
For example, TableOrder.UserID has a value of 250, but there is no matching TableUser.UserID key for 250.
Here's one way:
select * from TableOrder where UserID not in (select UserID from TableUser);
There are many different ways to write this sort of query.
The other common approach is a left-outer join:
SELECT * FROM TableOrder o
LEFT OUTER JOIN TableUser u ON o.UserID = u.UserID
WHERE u.UserID is NULL
This query can also be useful without the where clause, to browse through and see the corresponding values (if they exist), and see which ones have no match.
There were no FK Constraints in the tables to begin with. The were used like FK and PK but not coded -- the belief was that they were unnecessary overhead. So we have all the columns, but no coded constraints. When I went to put them in so that they would be enforced, I discovered that there were lots of violations.
Your question highlights the problem. They are not unnecessary overhead, they prevent people from general database asshattery.
Both Greg and Brad's answers helped me out.