My Access database has a query which, I suspect, is called by macros or other queries. Is there any way to run a Find on the "code" of all the macros and/or queries, to look for a text string (in this case, the query name)?
this lists all the tables & queries:
SELECT IIf([type] = 5, "Query", "Table") AS [Object type]
,MSysQueries.Flag AS [Query type]
,MSysObjects.NAME
,MSysObjects.Id
,MSysObjects.Type
FROM MSysObjects
LEFT JOIN MSysQueries ON MSysObjects.Id = MSysQueries.ObjectId
GROUP BY IIf([type] = 5, "Query", "Table")
,MSysQueries.Flag
,MSysObjects.NAME
,MSysObjects.Id
,MSysObjects.Type
HAVING (
(
(MSysObjects.NAME) NOT LIKE "~*"
AND (MSysObjects.NAME) NOT LIKE "Msys*"
)
AND (
(MSysObjects.Type) = 1
OR (MSysObjects.Type) = 4
OR (MSysObjects.Type) = 6
OR (MSysObjects.Type) = 5
)
)
ORDER BY IIf([type] = 5, "Query", "Table") DESC
,MSysQueries.Flag
,MSysObjects.NAME;
and this one lists each object and the queries that reference it:
SELECT [~MSys Tables & Queries].NAME AS [Object]
,MSysObjects.NAME AS [Used in query]
FROM [~MSys Tables & Queries]
LEFT JOIN (
MSysQueries LEFT JOIN MSysObjects ON MSysQueries.ObjectId = MSysObjects.Id
) ON [~MSys Tables & Queries].NAME = MSysQueries.Name1
GROUP BY [~MSys Tables & Queries].NAME
,MSysObjects.NAME
ORDER BY [~MSys Tables & Queries].NAME
,MSysObjects.NAME;
I don't know how to search through Macros the same way. Also, I'm not sure this always picks up objects used in Union queries.
I hope it gives you a place tro start.
You can install a free Access Add-in Access Dependency Checker, it can search strings thru all objects.
Related
I have multiple models in Sparx Enterprise Architect in file-based, i.e. using MS access.
I'm using a custom template to populate a table with data from object's properties, including some with <memo> fields.
This is the query i'm using in the template fragment:
SELECT obj.object_id,
obj.Stereotype,
objp.Property as Prop,
switch(objp.Value = '<memo>', objp.Notes, objp.Value LIKE '{*}',
NULL, 1=1, objp.Value) AS Val,
(SELECT tobj2.ea_guid & tobj2.Name FROM t_object tobj2 WHERE
tobj2.ea_guid = objp.Value) AS [Obj-Hyperlink]
FROM t_object obj
INNER JOIN t_objectproperties objp
ON (obj.object_id = objp.object_id)
WHERE obj.object_id = #OBJECTID# AND obj.Stereotype='Data-
Stream' AND objp.Property NOT IN ('isEncapsulated')
ORDER BY objp.Property ASC;
I found that the when these fields are longer than 249 chars I get an error message when generating the reports and the cell in the generated table is simply empty. This is also noticeable with a query:
The error I'm getting states:
"Error Processing xml document: an invalid character was found in text context"
Is there any workarround to enable including the <memo> fields' data with more than 249 chars in the reports?
Any help is much appreciated.
I've found a workaround for this by joining two queries with a "Union all". The first query will handle the non-memo fields with the switch function and the second one the memo fields without the switch function.
select
obj.object_id,
obj.Stereotype,
objp.Property as Prop,
objp.Notes AS Val,
(
SELECT
tobj2.ea_guid & tobj2.Name
FROM
t_object tobj2
WHERE
tobj2.ea_guid = objp.Value
) AS [Obj-Hyperlink]
from
t_objectproperties objp
left join t_object obj on (obj.object_id = objp.object_ID)
where
obj.object_id = #OBJECTID#
AND obj.Stereotype = 'Data-Stream'
AND objp.Property NOT IN ('isEncapsulated')
AND objp.Value = "<memo>"
UNION ALL
SELECT
obj2.object_id,
obj2.Stereotype,
objp2.Property as Prop,
switch(
objp2.Value LIKE '{*}', NULL, 1 = 1, objp2.Value
) AS Val,
(
SELECT
tobj2.ea_guid & tobj2.Name
FROM
t_object tobj2
WHERE
tobj2.ea_guid = objp2.Value
) AS [Obj-Hyperlink]
FROM
t_object obj2
INNER JOIN t_objectproperties objp2 ON (obj2.object_id = objp2.object_id)
WHERE
obj2.object_id = #OBJECTID#
AND obj2.Stereotype = 'Data-Stream'
AND objp2.Property NOT IN ('isEncapsulated')
and objp2.Value <> "<memo>"
order by
3 asc;
Thanks a lot #geertbellekens for your comment which was crucial to find this solution.
I have two tables (lets call them Parameters 1 and 2) which both have a many-many relationship with a third table (Options). I need to group the third table records into three groups:
Those exclusively related to [specific Parameter 1 record],
Those exclusively related to [specific Parameter 2 record] and
Those related to both [specific Parameter 1 record] and [specific Parameter
2 record].
I can ignore Option records not related to either of them.
I need to be able to specify which Parameter 1 and 2 records apply in a form (using combo boxes), and have VBA juggle the three lists in the background, updating them as the Option records they contain are "used" elsewhere in the form (with check boxes).
At the risk of asking a bad question I'll submit the code I have - even though it's not a code that fails, just the framework for one that isn't even finished enough to debug yet. I simply haven't got the tools to complete it, as I don't know what methods/properties of what things to use to do it, and can't seem to find the answers in my own research thus far. Comments directing me to other resources will be appreciated, even if you don't have an answer that you're sure is best practice.
Function SetOptions()
If IsNull(cmbParam1) Or IsNull(cmbParam2) Then
MsgBox "You must select both an Param1 and a Param2!", vbCritical, "Wait!"
Exit Function
End If
'Recordsets of allowed Options
Dim Param1Opt, Param2Opt, OverlapOpt
'create recordset of tblOption.Option(s) referenced in qryPr1Opt with Param1 from cmbParam1
Param1Opt = CurrentDb.OpenRecordset("SELECT tblPr1Opt.Option FROM tblPr1Opt " &_
"WHERE Param1 = '" & cmbParam1 & "';")
'create recordset of tblOption.Option(s) referenced in qryPr2Opt with Param2 from cmbParam2
Param2Opt = CurrentDb.OpenRecordset("SELECT tblPr2Opt.Option FROM tblPr2Opt " &_
"WHERE Param2 = '" & cmbParam2 & "';")
'create recordset of tblOption.Option(s) in qryOptOvrlp with Param2 and Param1 from form
OverlapOpt = CurrentDb.OpenRecordset("SELECT qryOptOvrlp.Option FROM qryOptOvrlp " &_
"WHERE Param1 = '" & cmbParam1 & "' AND Param2 = '" & cmbParam2 & "';")
OverlapNum = Param1Num + Param2Num
'Steps remaining:
'1. Get Param1Opt and Param2Opt to only include Options not in overlap
For Each oOpt In OverlapOpt
For Each aOpt In Param1Opt
If aOpt.Value = oOpt.Value Then
'filter this record out of Param1Opt
End If
Next aOpt
For Each gOpt In Param2Opt
If gOpt.Value = oOpt.Value Then
'filter this record out of Param2Opt
End If
Next gOpt
Next oOpt
'2. Get the data in Param1Opt, Param2Opt and OverlapOpt, as well as their
'corresponding Nums to be accessible/editable in other functions/subs
End Function
You can reference the values of controls in SQL statements run in the context of Access, using the following syntax:
Forms!FormName!ControlName
or using square brackets if needed:
Forms![Form Name]!ControlName
Therefore, instead of opening multiple recordsets, you can express each of your points as a single SQL statement with joined tables. You can then either set the RowSource of a combobox or listbox to the statement (if you are only using the statement in one place); or you can save the statement as an Access query, and use the query name as the RowSource (if you need the statement in multiple places).
Given the following schema:
and two comboboxes: cmbParam1 and cmbParam2 on a form named Form1, you can use SQL statements as follows:
1. Records from Options which match tblPr1Opt but have no match in tblPr2Opt
SELECT DISTINCTROW Options.Option
FROM (Options
INNER JOIN tblPr1Opt ON Options.Option = tblPr1Opt.Option)
LEFT JOIN tblPr2Opt ON Options.Option = tblPr2Opt.Option
WHERE tblPr2Opt.Option IS NULL
AND tblPr1Opt.Param1 = Forms!Form1!cmbParam1
Or using the query designer (note the arrow head next to tblPr2Opt; this indicates a left join):
2. Records from Options which match tblPr2Opt but have no match in tblPr1Opt:
SELECT DISTINCTROW Options.Option
FROM (Options
INNER JOIN tblPr2Opt ON Options.Option = tblPr2Opt.Option)
LEFT JOIN tblPr1Opt ON Options.Option = tblPr1Opt.Option
WHERE tblPr1Opt.Option IS NuLL
AND tblPr2Opt.Param2 = Forms!Form1!cmbParam2;
or in the query designer:
3. Records from Options which match on both:
SELECT Options.Option
FROM (Options
INNER JOIN tblPr1Opt ON Options.Option = tblPr1Opt.Option)
INNER JOIN tblPr2Opt ON Options.Option = tblPr2Opt.Option
WHERE tblPr1Opt.Param1 = Forms!Form1!cmbParam1
AND tblPr2Opt.Param2 = Forms!Form1!cmbParam2
Or in the query designer:
I'm trying to create a query that can run from a button in MS Access. The SQL query I've created is below:
PARAMETERS CASNUMBER Text ( 255 );
SELECT DISTINCT Chemical.Chemical_Name, Hazard.Hazard_Code, Hazard.Hazard_Text
FROM Chemical, Chemical_Hazard, Hazard
WHERE Chemical.Chemical_Id = Chemical_Hazard.Chemical_Id
and Chemical_Hazard.Hazard_Id = Hazard.Hazard_Id
and [CASNUMBER] = Chemical.CAS
;
How do I make it so that a MsgBox appears when there are no values returned?
I'd recommend join tables using JOIN instead of WHERE. Also you can avoid using parameter, which in most cases requres VBA code for query execution. Just create query without parameter, add CAS to columns list:
SELECT DISTINCT Chemical.Chemical_Name
,Hazard.Hazard_Code
,Hazard.Hazard_Text
,Chemical.CAS
FROM (
Chemical_Hazard INNER JOIN Chemical ON Chemical.Chemical_Id = Chemical_Hazard.Chemical_Id
)
INNER JOIN Hazard ON Chemical_Hazard.Hazard_Id = Hazard.Hazard_Id
And then check for CAS in code:
If DCount("*", "MyQuery", "CAS=" & lngCASNumber) = 0 then
MsgBox "CAS not found"
End If
I have two tables, packages (with id, name as attributes) and releases (with url, upload_time, downloaded_bytes as attributes). Every package can have arbitrary many releases. I want a list of all packages with their latest release.
Currently, I have the following working code:
sql = ("SELECT `packages`.`id`, `name` FROM `packages`")
cursor.execute(sql)
packages = cursor.fetchall()
for pkg in packages:
sql = ("SELECT `url` FROM `releases` "
"WHERE `package_id` = %s "
"AND `downloaded_bytes` = 0 "
"ORDER BY `upload_time` DESC LIMIT 1")
cursor.execute(sql, (pkg['id'], ))
url = cursor.fetchone()
if url is not None:
package_url = url['url']
package_analysis.main(pkg['name'], package_url)
logging.info("Package '%s' done.", pkg['name'])
However, I think this is an ugly solution as I execute a lot of queries where I should only execute one query.
Can I do this in one query? How would the query look like?
Please note: I only want one result for each package. That means, the package numpy should only give the result for url="https://pypi.python.org/packages/cp35/n/numpy/numpy-1.10.1-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" (version 1.10.1) and not 99 results.
What I've tried
SELECT
`packages`.`id`,
`packages`.`name`,
`releases`.`url`,
`releases`.`upload_time`,
`releases`.`release_number`
FROM
`packages`
JOIN
`releases` ON `releases`.`package_id` = `packages`.`id`
GROUP BY
`packages`.`name`
ORDER BY
`releases`.`upload_time` DESC
But that gives a seemingly random value for upload_time (and also url).
You can try this query:
select p.id, p.name, r.url, r.upload_time, r.release_number from
(select p.id, max(r.release_number) release_number from packages p
join releases r on p.id = r.package_id
group by p.id) a
join packages p on p.id = a.id
join releases r on r.release_number = a.release_number
It assumes that release_number is sortable, if not possible you can use max upload time instead.
Based on this answer (thank you Emiswelt) for mentioning it:
SELECT
`packages`.`id`,
`packages`.`name`,
`o`.`url`,
`o`.`upload_time`,
`o`.`release_number`
FROM
`releases` o
LEFT JOIN
`releases` b ON `o`.`package_id` = `b`.`package_id`
AND `o`.`upload_time` < `b`.`upload_time`
JOIN
`packages` ON `packages`.`id` = o.package_id
WHERE
`b`.`upload_time` is NULL
AND `o`.`downloaded_bytes` = 0
ORDER BY
`packages`.`name`
LIMIT 10
The query finishes execution within a fraction of a second.
I am stuck with this update query:
UPDATE [table1] n SET n.kdo = IIf( n.old_kdo IN (SELECT u.id FROM [table2] u WHERE u.id_c<>0),"1","0")
it gives me "Operation must use an updatable query" error (I have all read/write permission).
I have tried bypass it by using:
UPDATE [table1] n SET n.kdo = IIf( n.old_kdo IN (DLookup("id", "table2", "id_c<>0")),"1","0")
it works, but sadly it return first match only.
Anyone have any idea how to make it right? Would be some join query better solution?
Try replacing your subquery by a dFirst(), dCount() or similar function, and extend your criteria accordingly:
UPDATE [table1] n SET n.kdo =
iif(dCount("*", "table2", "id_c<>0 and id = " & n.old_kdo) > 0 ,"1","0")
Access is tricky for joins in Update queries.