I am converting my Access query to SQL view. One of the Access query has where condition where a user can input values
where table1.id=[Enter the ID of the user]
Is there a way to convert a query like this to T-SQL. It is important for me to leave the prompt as it is.
Well, first, there is little reason to convert to a pass-though query.
However, SQL Server cannot prompt you in access (or say a web site that uses SQL Server). So the GUI part must be created by YOUR web site, or say access client in this case.
It is usually best to build some prompt form with a button, since those automatic prompts that Access creates are VERY poor from a UI point of view.
As noted, it is VERY likely that you can just continue to use the access query.
However, if you need a pt query, then you use access code to ask/get the prompt value, and then add that to your query.
This will work:
Dim strSQL As String
Dim invoiceNum As String
strSQL = "select * from tblInvoices where invoiceNumber = "
invoiceNum = InputBox("enter Invoice Number")
If invoiceNum = "" Then Exit Sub
strSQL = strSQL & invoicenumber
With CurrentDb.QueryDefs("qryPassR")
.SQL = strSQL
End With
' now, docmd.OpenReport, or openform or
' whatever it is you wanted to do with the sql
However, as noted, for reports etc., I would build a nice form that allows the user to enter a value. The query prompts are pure torture to your users, and they are not user friendly at all.
Also, the above assumes that you going to open some report, or some such. If you need the data returned in a reocrdset, the use this:
Dim strSQL As String
Dim invoiceNum As String
dim rst As DAO.RecordSet
strSQL = "select * from tblInvoices where invoiceNumber = "
invoiceNum = InputBox("enter Invoice Number")
If invoiceNum = "" Then Exit Sub
strSQL = strSQL & invoicenumber
With CurrentDb.QueryDefs("qryPassR")
.SQL = strSQL
Set rst = .OpenRecordset
End With
And last but not least, as others suggested here, you should consider a stored procedure with parameters, as the above is subject to SQL injection.
Related
I have an Access application (Access Front-end, SQL backend using Linked tables) and I'm having this issue:
The user enters in a part number. Then they enter in a quantity. New business logic says I have to check this part number against a table, to see if we have quoted it to a customer within the past year. If we have, we can quote it now; if not, we have to reject the part.
When the program was originally written, they used a datasheet format to allow the user to copy from Excel a list of parts, paste them into the datasheet, and then copy and paste in a list of quantities. Once the quantity is entered/pasted for a line, that line is processed.
If I manually enter in a part number, then the quantity, the needed code checks to see if the part number has been quoted within the last year, and everything is peachy.
But if I copy and paste in a list of parts, the first time through the process it works fine; but every other time fails.
Here's the basic code:
Dim cn21 As ADODB.Connection
Set cn21 = New ADODB.Connection
Dim strsql21 As String
Dim cm21 As New ADODB.Command
Dim rs21 As New ADODB.Recordset
' gblODBCString = "ODBC;Description=PartsPortalsSql;DRIVER=SQL Server;SERVER=db-TEST-partsptl-primary;Trusted_Connection=Yes;APP=Microsoft Office 2010;DATABASE=PartsPortalSQL;"
cn21.Open gblODBCString
cm21.ActiveConnection = cn21
' All I want to know is how many records there are for this part within the last year...
strsql21 = "Select count(*) from tblQuoteDetail tqd INNER JOIN tblQuotes tq on tqd.quoteid = tq.quoteid WHERE " _
& " tqd.qdetailpartno = '" & Me.QDetailPartNo & "' AND tq.quotesentdate >= '" & OneYearAgo & "' AND tqd.qdetailunitprice > 0"
cm21.CommandText = strsql21
Set rs21 = New ADODB.Recordset
Set rs21 = cn21.Execute(strsql21, varparams, adCmdText)
If rs21(0) = 0 Then ' nothing found! can't be escalated...
blah blah blah...
end if
' done with this part... clean up
Set cm21 = Nothing
rs21.Close
Set rs21 = Nothing
Set cn21 = Nothing
Then it will return here when it gets to the next part...
But if i do it manually, it works fine. But when it is running through the loop of parts, it gets to the:
Set rs21 = cn21.Execute(strsql21, varparams, adcmdtext)
line
and takes about 30 seconds to 'process/time out', and then the rs21(0) returns "Run-time error '3265': Item cannot be found in the collection corresponding to the requested name or ordinal."
I've verified every field in the sql query is correctly populated. I've never run into this issue before.
Other things I've attempted - use DAO instead of ADODB... no luck...
If anyone has any suggestions I'm all ears... short of blowing it up... I'm in the testing phase of a replacement version, that doesn't use that copy/paste functionality. But that's still a month or two away from production.
Thanks
Access 2016, Linked tables to Microsoft SQL Server 2016 I believe...
Windows 10 64 bit
Also running on a VPN, connected to a VDI.
I htink youre using the wrong commands to check for recordsets. I could be wrong as I dont use ADO as much as I should, but here is my template for it if you thin itll help
'needs the MSO AtiveX Data Objects Library
Dim vbSql As String, cnnstr as string
Dim cnn As ADODB.Connection
Dim rs As New ADODB.Recordset
vbSql = "SELECT ;"
Set cnn = New Connection
cnnstr = ""
cnn.Open cnnstr
rs.CursorLocation = adUseClient
rs.Open vbSql, cnn
cnn.Close
Set cnn = Nothing
I'm trying to create in MS Access a pass trough query which will be connected to SQL server and use combo box from the form as a filter parameter in the WHERE statement part.
I know that connection and everything works because if I enter
SELECT * FROM mrch.Promo_Request_Base
I receive all the results.
Now when I try to enter something like
SELECT * FROM mrch.Promo_Request_Base WHERE mrch.Promo_Request_Base.Requestor_Name = 'UserABC';
then it also works.
It does not work for me if I enter SQL like this:
SELECT *
FROM mrch.Promo_Request_Base
WHERE (((mrch.Promo_Request_Base.Requestor_Name) = [Forms]![f_PromoRequest_VIEW_Header_001a]![Combo133]));
I also tried this:
SELECT *
FROM mrch.Promo_Request_Base
WHERE (((mrch.Promo_Request_Base.Requestor_Name) = [Forms]![f_PromoRequest_VIEW_Header_001a]![Combo133].Columns(0)));
[Combo133] has value 'UserABC' in it.
I would be very thankful if you could help me.
You don't.
Pass-through queries are passed to the data source as-is, and aren't parsed by Access at all. This means there's no way to use form-based parameters in a pass-through query.
Instead, use VBA to set parameters.
For how to do that, see How do I use parameters in VBA in the different contexts in Microsoft Access?. Specifically, the section on DAO applies to pass-through queries.
This also means you can't open the query for displaying. Use a form in datasheet view using VBA to set its own recordset instead. Do note that if a recordset requires parameters to be requeried, this can lead to trouble on sort/filter.
A pass-through query means it is executed server side. That server can no more go look into access and pull data then go and try and steal all your emails or financial data on your computer.
the simple solution then is to "process" or "evaluate" the expression BEFORE you send it to sql server. You can use the following:
Dim strSQL As String
strSQL = "SELECT * From mrch.Promo_Request_Base " & _
"WHERE mrch.Promo_Request_Base.Requestor_Name = '" & _
[Forms]![f_PromoRequest_VIEW_Header_001a]![Combo133] & "'"
With CurrentDb.QueryDefs("qryPass")
.SQL = strSQL
End With
' now code here to open form, or say launch report
DoCmd.OpenReport "rptPromoList", acViewPreview
Note that you have to ensure that the sql is formatted correctly for the server side.
So, in above, I am assume Requestor_Name is a text type of field. So,, that means you have to place quotes (I used single) around the expression. If that column you get from the combo box is a number, then the quotes are not required, and you would use this:
strSQL = "SELECT * From mrch.Promo_Request_Base " & _
"WHERE mrch.Promo_Request_Base.Requestor_Name = " & _
[Forms]![f_PromoRequest_VIEW_Header_001a]![Combo133]
So the other code would be the same - the only change in above was how I left out the adding of quotes (') around the expression.
Many thanks for your help.
At the end I did it differently. Im changing the PassTrough query via VBA :
Private Sub Command159_Click()
Dim db As dao.Database
Set db = CurrentDb
Dim qdf As dao.QueryDef
Set qdf = db.QueryDefs("q_PassThrough_VIEW_001a")
qdf.SQL = "SELECT * From mrch.Promo_Request_Last_Version_rpt_v " & _
"WHERE mrch.Promo_Request_Last_Version_rpt_v.F_Qtr_CD LIKE '" & _
[Forms]![f_PromoRequest_VIEW_Header_001a]![Combo145] & "%'"
qdf.Close
db.Close
Set qdf = Nothing
Set db = Nothing
End Sub
I have a multi user Access UI linked to a SQL Server database that is used to perform loan reviews for a mortgage company. Users are currently using the 'Find Record' function that already exists in Access and it takes a very long time to locate the record. While I do understand why it takes so long and what it theoretically needs to do, I can't figure out the best way to write code to do directly to the record needed. It needs to be a message box similar to the existing find record function, but that performs the most efficient way. I tried the following, which doesn't include a message box, and it doesn't work:
Private Sub txtFindLoan_AfterUpdate()
Dim sSQL As String
sSQL = "SELECT * FROM dbo_PreCloseAuditEnc WHERE LOAN_NUM = '" &
Me.txtFindLoan & "'"
Me.RecordSource = sSQL
Me.Requery
End Sub
Thanks in advance!
There is no bottleneck, except that you don't need a requery. And, of course, make sure you have an index on the LOAN_NUM field.
You could have an InputBox to pick up the loan number. The code could be called from a button:
Private Sub LoanButton_Click()
Dim sLoanNo As String
Dim sSQL As String
sLoanNo = InputBox("Loan Number:", "Select Loan Number")
If sLoanNo <> "" Then
' Input provided.
' Validate input.
' IsValidLoanNumber will be a function to do this. Must return True/False.
If IsValidLoanNumber(sLoanNo) Then
sSQL = "SELECT * FROM dbo_PreCloseAuditEnc WHERE LOAN_NUM = '" & sLoanNo & "'"
Me.RecordSource = sSQL
End If
End If
End Sub
You're probably off best using ADODB since you're only using external data, and binding the form directly to a filtered ADODB recordset.
As Sean Lange said, you should parameterize your query, and you can do that either using DAO or ADO, but not by modifying the Me.RecordSource property
Private Sub txtFindLoan_AfterUpdate()
Dim sSQL As String
'I'm assuming your table name in MS SQL is dbo.PreCloseAuditEnc
sSQL = "SELECT * FROM dbo.PreCloseAuditEnc WHERE LOAN_NUM = ?"
Dim adoConn As New ADODB.Connection
'Enter a valid OLEDB connection string here:
adoConn.Open "Provider=SQLNCLI11;Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes;"
Dim cmd As New ADODB.Command
cmd.ActiveConnection = adoConn
cmd.CommandText = sSQL
cmd.Parameters.Append cmd.CreateParameter(Type:=adChar, Value:=Me.txtFindLoan)
Me.RecordSet = cmd.Execute
End Sub
I am building a form in MS Access using linked ODBC tables which is to become a large input basis for some of our teams. I have most of it worked out however am trying to auto generate a Primary ID for the main table and populate the text box so the agent doesn't have to. Effectively building an auto number in SQL.
I have the generation and rolling edits in the ODBC tables working and am just stuck on getting the generated code into the relevant field. I am using a macro on button click and have the following code:
Private Sub cmdSubmitDetails_Click()
Dim strSQL As String
Dim rst As Recordset
Dim db As Database
Dim para As String
para = InputBox("Please Enter Your User ID:")
strSQL = "SELECT Min([P_ID]) AS ID FROM QA_IDS WHERE EV_ID = " & para & ";"
Set db = CurrentDb
Set rst = db.OpenRecordset(strSQL)
Me.ID.Text = rst!ID
rst.Close
Set rst = Nothing
Set db = Nothing
End Sub
Me.ID is the field I am trying to populate. It is erroring out in the line
Set rst = db.OpenRecordset(strSQL)
with the error Run-time error '3464' Data type mismatch in criteria expression.
It's my first real dabble in MS Access and I've searched for the solution online. Any help would be greatly appreciated.
I managed to achieve what I was trying using a different method and thought I would post for someone to find useful in the future.
To get around the issue of inconsistent datatype I used a query to run the SQL (including inputting the User ID) , and append it to a new table. Then pull the information from that table with a DLookup, then purge that table. I ended up with the following code.
Private Sub cmdSubmitDetails_Click()
Dim x As String
Dim y As String
Dim z As String
DoCmd.SetWarnings False
DoCmd.OpenQuery ("AppendID")
x = DLookup("[ID]", "[TempID]")
Me.ID = x
y = DLookup("[EV_ID]", "[TempID]")
Me.EVALUATOR_ID = y
DoCmd.OpenQuery ("qryDELETE_TEMP_ID")
DoCmd.OpenQuery ("qryAddNextCallID")
DoCmd.OpenQuery ("qryDELETE_MINIMUM_ID")
DoCmd.SetWarnings True
End Sub
`Dim con1 As New ADODB.Connection
Dim rs1 As New ADODB.Recordset
Dim sql1 As String
sql1 = "Update Balance set Balance_Amt = (Balance_Amt + " & a & ") where Company = " & Combo3.Text
con1.Execute (sql1)
"Can anyone say why this code does not work? It says No value for one or more required parameters"
I would guess that the immediate problem is that the SQL fragment
where Company = value
is invalid SQL. It should be quoted:
where Company = 'value'
But you really should be using SQL parameters.
I would have avoided this issue since the parameter would have been automatically quoted as necessary.
It would have made the code easier to read.
It would not be susceptible to SQL Injection attacks.
e.g.
Using cmd = new SqlCommand("UPDATE Balance SET Balance_Amt = (Balance_Amt + #a) WHERE Company=#company", con1)
cmd.Parameters.AddWithValue("#a", a)
cmd.Parameters.AddWithValue("#company", company)
cmd.ExecuteNonQuery()
End Using
Print out the sql statement and see if it is ok, copy/paste it to the sql management studio.
I think you are missing apostrophes around the string Combo3.Text.
Also consider what sql it would result in if Combo3.Text contains
'a'; delete from Balance