I'm a little confused...

  • Thread starter Thread starter ChrisM
  • Start date Start date
C

ChrisM

Hi,

I've recently 'inherited' a fairly large Access database (~100 tables and
~400 queries)

Not much in the way of documentation though :-(

What I'm wondering is if there is an easy way of working/listing out which
queries reference which tables, as I KNOW there are quite a few queries that
are obsolete, but it is proving quite difficult to work out exactly which
tables are surplus to requirements...

What would be helpful would be a report listing all queries, and showing a
list of tables/other queries referenced in each.

Is there a way of doing this?

Cheers,

Chris
 
Chris,

You need Total Access Analyzer from FMS:
http://www.fmsinc.com/products/analyzer/index.html

Although it might seem a bit expensive, in my opinion, it is worth it.

You can also try SpeedFerret from Black Moshannon:
http://www.speedferret.com/

A good freebie tool is the CSD Tools:
http://home.bendbroadband.com/conradsystems/accessjunkie/csdtools.html


Tom Wickerath
Microsoft Access MVP

http://www.access.qbuilt.com/html/expert_contributors.html
http://www.access.qbuilt.com/html/search.html
__________________________________________
 
ChrisM said:
I've recently 'inherited' a fairly large Access database (~100 tables and
~400 queries)

Not much in the way of documentation though :-(

What I'm wondering is if there is an easy way of working/listing out which
queries reference which tables, as I KNOW there are quite a few queries that
are obsolete, but it is proving quite difficult to work out exactly which
tables are surplus to requirements...

Ideally, you would be able to use ADO's OpenSchema method with the
VIEW_TABLE_USAGE Rowset
(http://msdn.microsoft.com/library/en-us/oledb/htm/oledbview_table_usage_rowset.asp)
to show the tables on which a VIEW ('stored query') is dependent.
Unfortunately, this rowset is not among the ones that Access/Jet
supports :(

Closer to the truth is that the existence of a table referred to in SQL
code, including that stored in database objects, it not actually tested
until the code hits the parser at runtime. For example:

CREATE VIEW DropThisView
AS
SELECT *
FROM TotallySpuriousName
;

OK so the parser doesn't like a non-existent table...

CREATE TABLE TotallySpuriousName (
col1 INTEGER
)
;
CREATE VIEW DropThisView
AS
SELECT *
FROM TotallySpuriousName
;
DROP TABLE TotallySpuriousName
;

....but it will happily DROP the table, demonstrating there is no
mechanism to check whether a VIEW is dependent on a table without
parsing the SQL definition of every VIEW in the catalog. Ditto for
PROCEDURES ('parameter queries').

I would recommend you think carefully before you get into the business
of parsing SQL yourself. When it comes to *formatting*, the Microsoft
SQL Parser Object Library 1.0 (SQLPARSE.DLL) component is helpful but
it does not attempt to differentiate between column names and table
names (and does not 'speak' Jet syntax anyhow).

Can anyone confirm whether any of the 'documenters' that are usually
advertised here (<g>) report on TABLE/VIEW/PROCEDURE dependencies?

Jamie.

--
 
Jamie,
Can anyone confirm whether any of the 'documenters' that are usually
advertised here (<g>) report on TABLE/VIEW/PROCEDURE dependencies?

Yes, I believe I can. If you'd like to send me a small test database that
includes some tables, views, procedures, queries, etc., I will run Total
Access Analyzer and SpeedFerret on it, and send you a copy of the results.

My e-mail address is available at the bottom of the contributors page
indicated below.


Tom Wickerath
Microsoft Access MVP

http://www.access.qbuilt.com/html/expert_contributors.html
http://www.access.qbuilt.com/html/search.html
__________________________________________
 
Tom said:
Yes, I believe I can. If you'd like to send me a small test database that
includes some tables, views, procedures, queries, etc., I will run Total
Access Analyzer and SpeedFerret on it, and send you a copy of the results.

Thank you, this is a generous offer.

Below is an existing script I had to create a test database with three
tables, two views ('stored queries') and two procedures ('parameter
queries'). I appended a DROP TABLE, just to make things interesting
<g>. The objects were originally for testing purposes i.e. I'm not
trying to pass this off as a typical database.

Things I hope a documenter would reveal, beyond the obvious, also being
things that I have noted some documenters do not do:

1) The data type, precision and scale of each column/parameter.
2) The default value of each proc parameter.
3) That TestTable1 has six CHECK constraints, two column-level, two
row-level and two table-level.
4) The tables and columns used in each CHECK constraint.
5) The table precedence e.g. TestTable0 > TestTable1.
6) That TestView1 uses base tables TestTable0 and TestTable1.
7) That TestView2 uses virtual table TestView1 and now-dropped
TestTable2.
8) That TestProc1 uses base tables TestTable1 and virtual table
TestView1, hence requires TestTable0.
That TestProc1 uses base tables TestTable1 and now-dropped TestTable2.

Perhaps you could post the results or a summary?

Sub tomtest()
Dim cat
Set cat = CreateObject("ADOX.Catalog")
With cat
.Create _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\JamieTest.mdb"
With .ActiveConnection
.Execute _
"CREATE TABLE TestTable0 ( " & _
"test_col1 DECIMAL(19, 4) NOT NULL " & _
") " & _
";"
.Execute _
"ALTER TABLE TestTable0 ADD " & _
"CONSTRAINT pk__TestTable0 " & _
"PRIMARY KEY (test_col1) " & _
") " & _
";"
.Execute _
"CREATE TABLE TestTable1 ( " & _
"test_col1 DECIMAL(19, 4) NOT NULL " & _
") " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT pk__TestTable1 " & _
"PRIMARY KEY (test_col1) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT fk__TestTable1__TestTable0 " & _
"FOREIGN KEY (test_col1) " & _
"REFERENCES TestTable0 (test_col1) " & _
"ON DELETE SET NULL " & _
"ON UPDATE CASCADE " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"COLUMN test_col2 DECIMAL(19, 4) NOT NULL " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT uq____TestTable1 " & _
"UNIQUE (test_col2) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT TestTable1__check__columnlevel1 " & _
"CHECK(test_col1 > 0) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT TestTable1__check__columnlevel2 " & _
"CHECK(NOT (test_col1 " & _
"BETWEEN 5.0000 AND 9.9999)) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT TestTable1__check__rowlevel1 " & _
"CHECK(test_col1 < test_col2) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT TestTable1__check__rowlevel2 " & _
"CHECK((test_col1 - INT(test_col1)) " & _
"> test_col2 - INT(test_col2))) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT TestTable1__check__tablelevel1 " & _
"CHECK(5 >= ( " & _
"SELECT COUNT(*) FROM TestTable1 AS T1))) " & _
";"
.Execute _
"ALTER TABLE TestTable1 ADD " & _
"CONSTRAINT TestTable1__check__tablelevel2 " & _
"CHECK(TestTable1.test_col1 > ( " & _
"SELECT COUNT(*) FROM TestTable0 AS T1) " & _
") " & _
";"
.Execute _
"CREATE TABLE TestTable2 ( " & _
"test_col1 DECIMAL(19, 4) NOT NULL " & _
") " & _
";"
.Execute _
"ALTER TABLE TestTable2 ADD " & _
"CONSTRAINT fk__TestTable1__TestTable1 " & _
"FOREIGN KEY (test_col1) " & _
"REFERENCES TestTable1 (test_col1) " & _
"ON DELETE SET NULL " & _
"ON UPDATE CASCADE " & _
";"
.Execute _
"CREATE VIEW TestView1 " & _
"AS " & _
"SELECT T0.test_col1 AS col1, " & _
"T1.test_col2 AS col2 " & _
"FROM TestTable0 AS T0 " & _
"LEFT JOIN TestTable1 AS T1 " & _
"ON T0.test_col1 = T1.test_col1 " & _
";"
.Execute _
"CREATE VIEW TestView2 ( " & _
"col1, col2 " & _
") AS " & _
"SELECT T2.test_col1, V1.col2 " & _
"FROM TestView1 AS V1 " & _
"LEFT JOIN TestTable2 AS T2 " & _
"ON V1.col2 = T2.test_col1 " & _
";"
.Execute _
"CREATE PROCEDURE TestProc1 ( " & _
"arg_col1 DECIMAL(19, 4) = 12.3456, " & _
"arg_col2 DECIMAL(19, 4) = 65.4321 " & _
") AS " & _
"INSERT INTO TestTable1 " & _
"(test_col1, test_col2) " & _
"SELECT DISTINCT arg_col1, arg_col2 " & _
"FROM TestTable1 AS T1 " & _
"WHERE NOT EXISTS ( " & _
"SELECT * " & _
"FROM TestView1 AS V1 " & _
"WHERE V1.col1 > arg_col1 " & _
") " & _
";"
.Execute _
"CREATE PROCEDURE TestProc2 ( " & _
"arg_col1 DECIMAL(19, 4) = 12.3456, " & _
"arg_col2 DECIMAL(19, 4) = 65.4321 " & _
") AS " & _
"INSERT INTO TestTable1 (test_col1, " & _
"test_col2) " & _
"SELECT DISTINCT arg_col1, arg_col2 " & _
"FROM TestTable0 AS T0 " & _
"WHERE NOT EXISTS ( " & _
"SELECT * " & _
"FROM TestTable2 AS T2 " & _
"WHERE T2.col1 > arg_col1 " & _
") " & _
";"
.Execute _
"DROP TABLE TestTable2 " & _
";"
.Close
End With
End With
End Sub

Thanks,
Jamie.

--
 
Tom said:
I have completed the results of an analysis using Total Access Analyzer.
Here you go! http://home.comcast.net/~tutorme2/taa/jamie.html

First, I'd like to say many thanks to Tom for taking the time to run
these reports and making them publicly available. What a great guy!

Second, I agree there is an impressive amount of information provided
in excess of the fairly picky points I was looking for. It is probably
the best Jet documenter I've seen; it certainly 'aims to please' and in
doing so it exceeded my expectations.

I'll address my points from earlier in the thread:

A few issues here:

· The columns' data type is correctly identified as 'Decimal' (e.g.
'Query Column Properties 1.snp') but not the precision (=19) or scale
(=4). Instead, I'm told 'size = 16' which makes me wonder: 16 what? I
understand a column of type DECIMAL occupies 17 bytes, so that's not
it...? In the report 'Query Parameters 1.snp', it can't identify the
type of parameters but it still knows they are '16'!

· In the report, "Errors, Suggestions and Performance Items", one
thing I am warned about is e.g. "TestTable1 has 1 decimal field." I'm
sorry, what was the error/suggestion/issue there?! Similarly, "Your
database contains one or more tables, but none of them are linked" Am I
*expected* to have tables linked to external data sources?! Could the
documentation clear up these matters...?

· The documenter has a problem with the fact the procs can't be
executes e.g. "TestProc2's parameters could not be documented."
Information about parameters remains available after a dependent table
has been dropped, as it is in another report (e.g. 'Query List with SQL
1.snp')

· One VIEW has been considered to be a PROCEDURE i.e. "TestView2's
parameters could not be documented." The VIEW was created with a list
of column correlation names that has been mistaken for a parameter
list.

Very weak in this area, as expected. The report 'Table Properties
1.snp' mentions one of the column-level CHECK constraints. Nothing else
anywhere. I wonder, if one of the row-level CHECK constraints was
defined using a record Validation Rule would it have been identified by
one of the reports...?

I think it's fair to say thank the table/proc 'precedence' is
documented well, same for the dropped tables, missing
columns/parameters, etc. However, there are a few issues:

· 'Relationships.snp' has misinterpreted the ON DELETE SET NULL
referential action as NO ACTION. Ideally, it would have been able to
determine that the SET NULL referential action was illegal considering
the NOT NULL nature of the referencing column.

· The SELECT * in an EXISTS subquery has been interpreted as a
column/parameter ('Query Columns Referenced.snp'). However, I think I
have uncovered a bug in the Jet engine (inadvertently; had I known
there was an issue I wouldn't have confused matters by using it here)
so it's no wonder the documenter has a problem with it!

· I'm impressed that TestView2 is correctly identified as 'updatable'
(as is TestView2even though a dependent table has been dropped but I
guess it means 'in principle') but I am less impressed that the same
report tells me that an 'Append' action would return records. I
couldn't get my head around whether an INSERT proc should be considered
'updatable'!

· 'Table Indexes and Properties 1.snp' tells me that my PRIMARY KEYs
are not clustered. That's not my understanding but considering this is
a contentious issue (we've been here before, Tom <g>: see
http://groups.google.com/group/microsoft.public.access/msg/b2d06df1dd151615)
the best approach could be to document as Clustered=N/A for Jet tables.


· I am very confused by the report 'Query Dictionary.snp', though it
may just be bad luck that some of the minor issues above appear
together in one smallish report. For me, this sums up this documenter:
if you peruse *all* the reports you get a fairly complete picture,
however many of in the individual reports contain information that
conflicts with another report.

· There are some other quirks but not unexpected in context e.g.
records = 0, record size (B) = 46 ('Table List 3.snp').

PS Can anyone tell me the meaning of the ADO/Jolt column in e.g. 'Query
List 1.snp'? Thanks.

Jamie.

--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top