How to substitute a variable into an OpenRecordSet query - ms-access

I am almost there:
The variable strCons contains a number and I would like to add this to the SQL. When I do this like below, I get this run-time error:
3061 Too few parameters. Expected 1.
When I replace strCons with a number it works. Tried to find out why with no luck.
Set rs = CurrentDb.OpenRecordset("SELECT Member.HomeEmail FROM Member INNER JOIN MemberRole ON Member.MemberID = MemberRole.MemberID WHERE (((MemberRole.AreaID)= strCons) AND ((MemberRole.RoleID)=1) AND ((MemberRole.FinishDate) Is Null)) ORDER BY Member.Surname")
strEmailTD = rs.Fields(0).Value
rs.Close

You can use:
Set rs = CurrentDb.OpenRecordset("SELECT Member.HomeEmail FROM Member INNER JOIN MemberRole ON Member.MemberID = MemberRole.MemberID WHERE (((MemberRole.AreaID)=" & strCons & ") AND ((MemberRole.RoleID)=1) AND ((MemberRole.FinishDate) Is Null)) ORDER BY Member.Surname")

Related

Formatting a listbox alternative [duplicate]

I am using the below SQL, it works fine if I run it from query builder but once I have put it in VBA it throws out an error:
Code:
With CurrentDb.CreateQueryDef("", "SELECT [_tbl_Structure].[User Name], tbl_Genesys_Daily.Field32, [_tbl_Structure].[Supervisor Emp Num], [_tbl_Structure].Supervisor FROM _tbl_Structure RIGHT JOIN tbl_Genesys_Daily ON [_tbl_Structure].[User ID] = tbl_Genesys_Daily.Field5 WHERE ((([_tbl_Structure].Supervisor)=?));")
.Parameters(0) = [Forms]![frm_Manager_Stats_NEW]![Text279]
Set lvxObj = AvailabilityCap.Object
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
End With
Error:
Too few parameters. Expected 1. (Runtime 3061)
Any help on understanding why this works for one but not another is appreciated
Form- and report-based parameters are only available in the GUI context (queries run using the GUI, forms, reports, macros and DoCmd.RunSQL). You're probably executing this through CurrentDb, and need to use a querydef instead.
With CurrentDb.CreateQueryDef("", "SELECT [_tbl_Structure].[User Name], tbl_Genesys_Daily.Field32, [_tbl_Structure].[Supervisor Emp Num], [_tbl_Structure].Supervisor FROM _tbl_Structure RIGHT JOIN tbl_Genesys_Daily ON [_tbl_Structure].[User ID] = tbl_Genesys_Daily.Field5 WHERE ((([_tbl_Structure].Supervisor)=?));")
.Parameters(0) = [Forms]![frm_Manager_Stats_NEW]![Text279]
Set rs = .OpenRecordset
End With
You can learn more about the different types of parameters, and when to use which one, in this answer

Too Few Parameters in Access VBA but works in Query builder

I am using the below SQL, it works fine if I run it from query builder but once I have put it in VBA it throws out an error:
Code:
With CurrentDb.CreateQueryDef("", "SELECT [_tbl_Structure].[User Name], tbl_Genesys_Daily.Field32, [_tbl_Structure].[Supervisor Emp Num], [_tbl_Structure].Supervisor FROM _tbl_Structure RIGHT JOIN tbl_Genesys_Daily ON [_tbl_Structure].[User ID] = tbl_Genesys_Daily.Field5 WHERE ((([_tbl_Structure].Supervisor)=?));")
.Parameters(0) = [Forms]![frm_Manager_Stats_NEW]![Text279]
Set lvxObj = AvailabilityCap.Object
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
End With
Error:
Too few parameters. Expected 1. (Runtime 3061)
Any help on understanding why this works for one but not another is appreciated
Form- and report-based parameters are only available in the GUI context (queries run using the GUI, forms, reports, macros and DoCmd.RunSQL). You're probably executing this through CurrentDb, and need to use a querydef instead.
With CurrentDb.CreateQueryDef("", "SELECT [_tbl_Structure].[User Name], tbl_Genesys_Daily.Field32, [_tbl_Structure].[Supervisor Emp Num], [_tbl_Structure].Supervisor FROM _tbl_Structure RIGHT JOIN tbl_Genesys_Daily ON [_tbl_Structure].[User ID] = tbl_Genesys_Daily.Field5 WHERE ((([_tbl_Structure].Supervisor)=?));")
.Parameters(0) = [Forms]![frm_Manager_Stats_NEW]![Text279]
Set rs = .OpenRecordset
End With
You can learn more about the different types of parameters, and when to use which one, in this answer

Errors in UPDATE query - VB6 DAO Access

A simple UPDATE query with INNER JOIN is causing me problems, using VB6 and DAO on an Access .MDB database.
I thought it would be simple, but whatever changes I make generate errors.
My query is:
UPDATE work
INNER JOIN emp ON work.ref = emp.ref
SET work.code1 = emp.code1
This generates run-time error 3075 Syntax error in query expression 'work.ref = emp.ref'.
I get a similar error with:
UPDATE work w
INNER JOIN emp ON w.ref = emp.ref
SET w.code1 = emp.code1
and
UPDATE [work] w
INNER JOIN emp ON w.ref = emp.ref
SET w.code1 = emp.code1
and also if I use alias e for table emp.
I cannot use a FROM clause, which is not supported in Access (Thanks though #MarkKram)
I have to use DAO 3.51 (old!) in VB6, which cannot easily be changed.
I have tried square brackets around the first reference to work as in UPDATE [work] (as I need this in a simple SELECT * FROM [work]) as well as various combinations with and without square brackets around table names and column names. But still it fails.
Do you have any suggestions please?
Dim ws As DAO.Workspace
Dim DB As DAO.Database
Dim szSQL As String
Set ws = gWS
Set DB = gWS.OpenDatabase(WorkFile)
szSQL = "UPDATE work INNER JOIN emp ON work.ref = emp.ref SET work.code1 = emp.code1 WHERE work.trancode = 'P'"
DB.Execute szSQL
Set DB = Nothing
Set ws = Nothing
Try this:
UPDATE work, emp
SET work.code1 = emp.code1
WHERE work.ref = emp.ref AND work.transcode ='P'

VB.Net) using condition data reader on join tables

I'm trying to collect data from joining table and currently there is a null displaying (no error found). I think my code isn't efficient tough. But here it is what I'm trying:
conn.Open()
sqlcmd = New MySqlCommand("select tabsen.id_absen, tsiswa.NIS, tsiswa.nama, tabsen.alpa, tabsen.izin, tabsen.sakit, tabsen.tahun_ajaran from tabsen join tsiswa on tabsen.NIS = tsiswa.NIS where tsiswa.NIS like '%" & txtnis.Text & "%'", conn)
dr = sqlcmd.executereader()
dr.Read()
If dr.HasRows Then
txtid.Text = dr.Item("id_absen")
txtnis.Text = dr.Item("NIS")
txtnama.Text = dr.Item("nama")
txta.Text = dr.Item("alpa")
txti.Text = dr.Item("izin")
txts.Text = dr.Item("sakit")
cmbtahun.Text = dr.Item("tahun_ajaran")
txta.Focus()
btnsave.Text = "UPDATE"
btndelete.Enabled = True
txtjumlah.Enabled = True
cmbpredikat.Enabled = True
cmbtahun.Enabled = True
txtnis.Enabled = False
dr.Close()
Else
While dr.Read()
txtnama.Text = dr("nama")
End While
dr.Close()
MsgBox("data absensi belum diisi")
End If
conn.Close()
If row found, it works like a charm. But when its empty on table 'tabsen', there is no error but txtnama.Text didn't show their 'nama'.
the problem
I think everyone will understand by looking the code. I can't explain much as my English isn't well enough.
... from tabsen join tsiswa on ...
This produces an Inner Join on the two tables which will only provide results if both tables have matching data.
Use either Right (Outer) Join
... from tabsen right join tsiswa on ...
Or Left (Outer) Join
... from tsiswa left join tabsen on ...
Having said that, be aware that if tabsen does not contain matching rows all of its attributes are NULL values.
So you have to check that when assigning values from the datareader to the textboxes:
Dim id_absen = dr.Item("id_absen")
txtid.Text = If(id_absen<> DBNull.Value, id_absen.ToString(), String.Empty)
...
Btw...I would recommend you set Option Strict On at the very top of your VB file. Will give you some compile errors but save you alot of mean bugs in the future.

Why would AccessDataSource return different results to query in Access?

I have a query to return random distinct rows from an Access database. Here is the query:
SELECT * FROM
(SELECT DISTINCT m.MemberID, m.Title, m.FullName, m.Address,
m.Phone, m.EmailAddress, m.WebsiteAddress FROM Members AS m INNER JOIN MembersForType AS t ON m.MemberID = t.MemberID WHERE
(Category = 'MemberType1' OR Category = 'MemberType2')) as Members
ORDER BY RND(members.MemberID) DESC
When I run this in Access it returns the rows in different order every time, as per the random sort order. When I run it through my web app however the rows return in the same order every time. Here is how I call it in my code-behind:
private void BindData()
{
using (AccessDataSource ds = new AccessDataSource("~/App_Data/mydb.mdb", GetSQLStatement()))
{
ds.DataSourceMode = SqlDataSourceMode.DataReader;
ds.CacheDuration = 0;
ds.CacheExpirationPolicy = DataSourceCacheExpiry.Absolute;
ds.EnableCaching = false;
listing.DataSource = ds.Select(new DataSourceSelectArguments());
listing.DataBind();
if (listing.Items.Count == 0)
noResults.Visible = true;
else
noResults.Visible = false;
}
}
I added in all that stuff about caching because I thought maybe the query was being cached but the result was the same. I put a breakpoint in the code to make sure the query was the same as above and it was.
Any ideas? This is driving me nuts.
When executing the ACE/Jet RND function against a new connection the same seed value is used each time. When using MS Access you are using the same connection each time, which explains why you get a different value each time.
Consider these VBA examples: the first uses a new connection on each iteration:
Sub TestDiff()
Dim con As Object
Set con = CreateObject("ADODB.Connection")
With con
.ConnectionString = _
"Provider=MSDataShape;Data " & _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\Tempo\Test_Access2007.accdb"
.CursorLocation = 3
Dim i As Long
For i = 0 To 2
.Open
Debug.Print .Execute("SELECT RND FROM OneRowTable;")(0)
.Close
Next
End With
End Sub
Output:
0.705547511577606
0.705547511577606
0.705547511577606
Note the same value each time.
The second example uses the same connection on each iteration (the .Open and .Close statements are relocated outside the loop):
Sub TestSame()
Dim con As Object
Set con = CreateObject("ADODB.Connection")
With con
.ConnectionString = _
"Provider=MSDataShape;Data " & _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\Tempo\Test_Access2007.accdb"
.CursorLocation = 3
.Open
Dim i As Long
For i = 0 To 2
Debug.Print .Execute("SELECT RND FROM OneRowTable;")(0)
Next
.Close
End With
End Sub
Output:
0.705547511577606
0.533424019813538
0.579518616199493
Note different values each time.
In VBA code you can use the Randomize keyword to seed the Rnd() function but I don't think this can be done in ACE/Jet. One workaround is to use the least significant decimal portion of the ACE/Jet the NOW() niladic function e.g. something like:
SELECT CDBL(NOW()) - ROUND(CDBL(NOW()), 4) FROM OneRowTable
I would move the RND into the inner SELECT
SELECT * FROM
(SELECT DISTINCT m.MemberID, RND(m.MemberID) as SortOrder, m.Title,
m.FullName, m.Address, m.Phone, m.EmailAddress, m.WebsiteAddress
FROM Members AS m
INNER JOIN MembersForType AS t ON m.MemberID = t.MemberID
WHERE
(Category = 'MemberType1' OR Category = 'MemberType2')) as Members
ORDER BY
Members.SortOrder DESC
You can use time as one argument to the RND field
Dim Now As DateTime = DateTime.Now
Dim millSec As Integer = Now.Millisecond
finalQuery = "SELECT * FROM wordInfo ORDER BY Rnd(-(1000* ROUND(" + millSec.ToString("N") + ", 0)) * [ID])"
So here from date and time value, millisecond value is taken which will be integer and it is used in sql query by rounding it.
wordInfo is table name
ID is the column name in database table
This gives random order every time (since millisecond value is different) be it same connection or new connection.