I have created a form for searching data by keyword, and assign this vba code to button's click event:
Dim sql As String
sql = "SELECT MD.[id], MD.[status], MD.[milnum], MD.[sname], MD.[mother], MD.[grade], MD.[gradetype], MD.[spcode], MD.[spes], MD.[unit] FROM MD WHERE (MD.[status] LIKE '*" & Me.tstate & "*') AND (MD.[milnum] LIKE '*" & Me.tnumber & "*') AND (MD.[sname] LIKE '*" & Me.tname & "*') AND (MD.[mother] LIKE '*" & Me.tmother & "*') AND (MD.[grade] LIKE '*" & Me.tgrade & "*') AND (MD.[gradetype] LIKE '*" & Me.ttype & "*') AND (MD.[spcode] LIKE '*" & Me.tcode & "*') AND (MD.[spes] LIKE '*" & Me.tspes & "*') AND (MD.[unit] LIKE '*" & Me.tunit & "*')order by MD.[id]"
Me.MD_Sheet.Form.RecordSource = sql
Me.MD_Sheet.Form.Requery
But when I doing a search, the query doesn't bring all results, for example when I write nothing in the textboxex it should brings all records from table MD but it doesn't, it just brings some records.
I create another button and assign same code to 'click event' with new sql statement:
Dim sql As String
sql = "SELECT MD.[id], MD.[status], MD.[milnum], MD.[sname], MD.[mother], MD.[grade], MD.[gradetype], MD.[spcode], MD.[spes], MD.[unit] FROM MD"
Me.MD_Sheet.Form.RecordSource = sql
Me.MD_Sheet.Form.Requery
And then it brings all records.
The records in MD table are about 25000 records.
Try applying Nz, not fast but simple:
AND (Nz(MD.[spcode]) LIKE '*" & Me.tcode & "*')
Related
I have declared variables that store the name of columns from a SQL Table as well as variables that store their corresponding "values to find".
Dim sColumn1 As String
Dim sColumn2 As String
Dim sColumn3 As String
Dim sValue1 As String
Dim sValue2 As String
Dim sValue3 As String
sColumn1 = Sheets(1).Range("A1").Value
sColumn2 = Sheets(1).Range("B1").Value
sColumn3 = Sheets(1).Range("C1").Value
sValue1 = Sheets(1).Range("A2").Value
sValue2 = Sheets(1).Range("B2").Value
sValue3 = Sheets(1).Range("C2").Value
I want to make a dynamic query like this:
StrQuery = "SELECT * FROM dbo.Table1 WHERE ('" & sColumn1 & "') LIKE ('" & sValue1 & "') AND ('" & sColumn2 & "') LIKE ('" & sValue2 & "') AND ('" & sColumn3 & "') LIKE ('" & sValue3 & "')"
This code does not generate any errors but IT DOES NOT pull any records either. I have confirmed and all the variables are being assigned the right values.
The query above works fine if I replace the Column variables for the actual column names in the SQL Table. Like this:
StrQuery = "SELECT * FROM dbo.Table1 WHERE Column1 LIKE ('" & sValue & "') AND Column2 LIKE ('" & sValue2 & "') AND Column3 LIKE ('" & sValue3 & "')"
With this string I get results without any problem but the columns will be dynamic. Users will choose from a variety of 15 columns.
Why is it that when I use the Variable it does not work even though I know the value of the variables matches exactly the names of the Columns in the SQL Table?
Am I using the wrong format in the string so that it reads the actual value stored within the variables?
Warnings above about using parameterized queries still apply but this is how you would get this to work:
StrQuery = "SELECT * FROM dbo.Table1 WHERE " & _
sColumn1 & " LIKE ('%" & sValue & "%')" & _
" AND " & sColumn2 & " LIKE ('%" & sValue2 & "%')" & _
" AND " & sColumn3 & " LIKE ('%" & sValue3 & "%')"
The answer by #TimWilliams should address the problem of not getting any result, provided the input is valid. However, as stated in the comments, the code is a bit brittle because entering malformed or otherwise inappropriate values into the fields of the sheet might produce interesting results. So, I would like to suggest a somewhat more robust approach than simply executing the SQL string.
If you are using ADO to talk to the SQL Server, you can call stored procedures on it as explained in this SO answer. Furthermore, provided you are at least on SQL Server 2008, there is the stored procedure sp_executesql. This stored procedure allows you to execute a SQL string containing parameters. The first parameter is the SQL string, the second a string containing the parameter list and the following parameters are the actual parameters for the query. This allows you to pass in the strings representing the LIKE pattern as actual string parameters. So, no matter what the values are, they cannot break the query itself.
Regarding the column names, you should at least escape them with square brackets. That is not waterproof, but it already goes a long way regarding accidentally malformed values.
The result would be something like
sqlString = "SELECT * FROM dbo.Table1 " & _
"WHERE [" & sColumn1 & "] LIKE #value1 " & _
" AND [" & sColumn2 & "] LIKE #value2 " & _
" AND [" & sColumn3 & "] LIKE #value3 "
parameterDeclarationString = "#value1 AS NVARCHAR(1000)," & _
"#value2 AS NVARCHAR(1000)," & _
"#value3 AS NVARCHAR(1000)"
Note that the max length of the parameters is just an arbitrary guess for a sensible upper limit.
I have put together some code in VBA which exports data from an excel sheet to a Data Base, this code (below) currently just inserts the data, but I would like to insert it based on a key (the date). So if the date already exists then in the DB the record associated with that date is replaced, if the date does not already exist, then it is inserted as usual.
Current code:
Sub SendData(AB As String, CD As String, EF As String, GH As String, IJ As String, KL As Double, MN As Double, PQ As Double, RS As Double)
Dim Date As String, Entity As String, area As String, unit As String, name As String, surname As String
Dim day As Double, weekly As Double, month As Double, year As Double
Dim objConn As ADODB.Connection
Set objConn = New ADODB.Connection
objConn.ConnectionString = "Provider=SQLOLEDB;Data Source=source;Initial Catalog=Title;Integrated Security=SSPI"
objConn.Open
Set objRec = New ADODB.Recordset
Date = Format(Range("date").Value, "YYYY-MM-DD")
Entity = AB
area = CD
unit = EF
name = GH
surname = IJ
daily = KL
weekly = MN
month = PQ
year = RS
StrSQL = "insert into table_name values ('" & Date & "', '" & Entity & _
"','" & area & "','" & unit & "','" & name & "','" & surname & "'," & daily & "," & weekly & "," & month & "," & year & ")"
Set objRec = objConn.Execute(StrSQL)
objConn.Close
Set objConn = Nothing
end sub
I am a bit confused where to place the key...
Thanks
You can do something like
StrSQL = "SELECT * FROM table_name"
objRec.Open StrSQL, objConn, , adLockOptimistic
objRec.Find "[date_value] = #" & Date & "#",,,adBookmarkFirst
If objRec.EOF Then
objRec.AddNew "[date_value] = #" & Date & "#"
End If
objRec![Entity] = Entity
'repeat for all required fields
objRec.Update
objRec.Close
I'm not 100% sure there is no minor error, as I "translated" it from my own working code, but general idea and instructions should be correct. This way you leverage recordset mechanics. I'm not sure about performance, maybe somebody more advanced will criticize it for being slow, but it works for me.
Look at sql joins you can do a join for the update and then another for the insert, if you are doing an entire range, if not use something like select count(ID) from [table_name] where [date_value]='your date' and use an if statement based on the resultant recordsets recordcount or do a select [date_value] from [table_name] of the destination table at the start of the proc in a separate rst and use .find to see if it's there
For one thing, I would change that 'Date' to something like 'TheDate', or some other descriptive, but non-reserved kind of word. Also, insert is insert and update is update. The Update (not insert) should be something like this:
StrSQL = "UPDATE table_name SET values ('" & Date & "', '" & Entity & _
"','" & area & "','" & unit & "','" & name & "','" & surname & "'," & daily & "," & weekly & "," & month & "," & year & ")
WHERE " & sWhere
Or, consider using the MERGE clause.
I am trying to update access table using simple VBA code, however it finished with an error. I have tried various ways to solve it but without success.
Could you please help? The code is as follow:
strSQL = "UPDATE Projects " & _
"SET Projects.id_status = '" & Me.T_project_s.Value & "' " & _
"WHERE Projects.id_project = '" & Me.curr_open.Value & "';"
I have also tried:
strSQL = "UPDATE Projects " & _
"SET Projects.id_status = [" & Me.T_project_s.Value & "] " & _
"WHERE Projects.id_project = [" & Me.curr_open.Value & "];"
or
strSQL = "UPDATE [Projects] " & _
"SET [Projects].[id_status] = '" & Me.T_project_s.Value & "' " & _
"WHERE [Projects].[id_project] = '" & Me.curr_open.Value & "';"
But it asks for a data which is available in those fields.
Your suggestion helped. I started with only a text then I have changed particular variables I wanted to be read. So in the Where statement there is no need to have beside "" also '' :).
strSQL = "UPDATE [Projects] " & _
"SET [Projects].[id_status] = '" & Me.T_project_s.Value & "' " & _
"WHERE [Projects].[id_project] = " & Me.curr_open.Value & ";"
Thanks.
Once again, here is an example where parameterization (an industry best practice in SQL programming) helps beyond avoiding SQL injection. With querydef parameters you:
avoid the need of quote enclosure;
avoid string interpolation of variables;
abstract data (i.e., VBA variables) from code (i.e., SQL statement) for cleaner scripts;
(plus as OP found out with mixed types) explicitly define the data types of values to be binded;
execute the query via DAO for smoother user interface than DoCmd.RunSQL that raises warnings to users.
Temp Query
Dim qdef As QueryDef
' PREPARED STATEMENT, DEFINING PLACEHOLDERS (NO DATA)
strSQL = "PARAMETERS [project_s_param] Text(255), [curr_open_param] Long;" & _
" UPDATE [Projects]" & _
" SET [Projects].[id_status] = [project_s_param]" & _
" WHERE [Projects].[id_project] = [curr_open_param];"
' CREATE UNNAMED TEMP QUERYDEF, ASSIGNING PREPARED STATEMENT
Set qdef = CurrentDb.CreateQueryDef("", strSQL)
' BIND VBA VALUES TO PARAMETER PLACEHOLDERS
qdef![project_s_param] = Me.T_project_s.Value
qdef![curr_open_param] = Me.curr_open.Value
' EXECUTE ACTION
qdef.Execute dbFailOnError
Set qdef = Nothing
Saved Query
Even better, save entire prepared statement as a stored Access query and avoid any SQL in VBA.
SQL (save as any regular query object whose name is referenced in VBA)
PARAMETERS [project_s_param] Text(255), [curr_open_param] Long;
UPDATE [Projects]
SET [Projects].[id_status] = [project_s_param]
WHERE [Projects].[id_project] = [curr_open_param]
VBA
Dim qdef As QueryDef
' REFERENCE EXISTING QUERYDEF, ASSIGNING PREPARED STATEMENT
Set qdef = CurrentDb.QueryDefs("mySavedQuery")
' BIND VBA VALUES TO PARAMETER PLACEHOLDERS
qdef![project_s_param] = Me.T_project_s.Value
qdef![curr_open_param] = Me.curr_open.Value
' EXECUTE ACTION
qdef.Execute dbFailOnError
Set qdef = Nothing
When I run a SQL insert command that gets an image and other data from a table in a Oracle Linked Server, inserting it in a SQL-Server, it works. When I run the exact same query inside a Visual Basic 6 program, the insert also works but the image isn't inserted.
The linked server part is working, as I can make several queries with success.
The insert I'm running is the one below. Notice that in both scenarios, the insert doesn't throw an error; they work in VB and Management Studio, BUT, when running through VB, just the image doesn't come.
INSERT INTO Employees
(
PhotoEmployee,
TheID,
Name
)
VALUES
(
(Select FOTO_Humanus From OPENQUERY(ORACLE_LinkedServer, 'Select FOTO.pesFoto FOTO_Humanus FROM Pessoa_Foto1 FOTO WHERE FOTO.pesCodPessoa = 32892')),
'900397',
'MARCELO ROCHA'
)
I've searched a lot but I couldn't find anyone with a similar problem.
The SQL-Server field that is receiving the image is from the IMAGE type.
In Oracle, the image is stored in a field that is from the type LONG RAW.
Can you help?
EDIT: (added more details)
The connection is ok... im pretty sure of that. Also, there is no error when I execute the SQL command or connecto to the database: Everythings works fine except for this image.. that doesnt get inserted in the destination database. All ohter fields are inserted without problems. All fields are in the same table.
The Visual Basic 6 code that i'm using is the following.
1 - O populate an array with the exact query I need
2 - Soon later I iterate in this array, executing the SQL query.
Here is the VB code:
SQLOracleTemp = "Select FOTO.pesFoto FOTO_Humanus FROM Pessoa_Foto1 FOTO WHERE FOTO.pesCodPessoa = 32892"
NomeLinkedServer = "ORACLE_LinkedServer"
SQL_InsertColab = "INSERT INTO Employees" & vbCrLf
SQL_InsertColab = SQL_InsertColab & " (" & vbCrLf
SQL_InsertColab = SQL_InsertColab & " funFotoColaborador," & vbCrLf
SQL_InsertColab = SQL_InsertColab & " TheID," & vbCrLf
SQL_InsertColab = SQL_InsertColab & " Name" & vbCrLf
SQL_InsertColab = SQL_InsertColab & " )" & vbCrLf
SQL_InsertColab = SQL_InsertColab & " VALUES" & vbCrLf
SQL_InsertColab = SQL_InsertColab & " (" & vbCrLf
SQL_InsertColab = SQL_InsertColab & " (Select FOTO_Humanus From OPENQUERY(" & NomeLinkedServer & ", '" & SQLOracleTemp & "'))," & vbCrLf
SQL_InsertColab = SQL_InsertColab & " " & aColabs_Insert(UBound(aColabs_Insert)).IDOAS & "," & vbCrLf
SQL_InsertColab = SQL_InsertColab & " " & aColabs_Insert(UBound(aColabs_Insert)).Nome & vbCrLf
SQL_InsertColab = SQL_InsertColab & " )" & vbCrLf
aSQL(UBound(aSQL)) = SQL_InsertColab
ReDim Preserve aSQL(UBound(aSQL) + 1)
For ContaSQL = 0 To UBound(aSQL)
if aSQL(ContaSQL) <> "" then
gConexao_Banco.Execute aSQL(ContaSQL)
enf if
Next
This may not be the exact answer but I don't know how to show code formatting in comment.
You have ReDim Preserve aSQL(UBound(aSQL) + 1) after aSQL(UBound(aSQL)) = SQL_InsertColab. Sounds strange but Probably this is correct as per your logic. Now after this you execute an array of sqlstatement in the for loop. So the last item in the array which still empty gets executed in the for loop and obviously it fails. Anyway try below. In the loop last array item doesn't execute. Check with your scenario and update it accordingly.
For ContaSQL = 0 To UBound(aSQL)-1
gConexao_Banco.Errors.Clear
gConexao_Banco.Execute aSQL(ContaSQL)
If gConexao_Banco.Errors.Count > 0 Then
For i = 0 To gConexao_Banco.Errors.Count
Debug.Print gConexao_Banco.Error(i).Number
Debug.Print gConexao_Banco.Error(i).Source
Debug.Print gConexao_Banco.Error(i).Description
Next i
End If
Next
I have an Access Frontend with a SQL Server backend.
On one of the forms, there is a bit of VBA to keep an "Audit Log" of the changes.
In one procedure there are these 2 bits of code, the first works, but the second gives an error
Working:
sSQL = "DELETE FROM [dbo_EventReport_Audit_Temp_Before];"
CurrentProject.Connection.Execute sSQL
Not working a few lines down:
sSQL = "INSERT INTO [dbo_EventReport_Audit_Temp_Before] (<TABLE COLUMNS>) SELECT <TABLE COLUMNS> FROM [dbo_EventReport] WHERE ((Event_ID)= <EVENT_ID>");"
CurrentProject.Connection.Execute sSQL
So the first statement deletes any records in the table. This works fine, as I've inserted dummy data and stepped through the code and seen it be deleted.
But the second statement causes an error:
Error -2147467259: ODBC--connection to 'EventsDB' failed.
Anyone any idea why the first statement works ok, but the second fails?
Extracting the value of sSQL for the second statement and manually running it through an SQL Query in Access inserts the data into the table.
EDIT:
I didn't want to post the full statement as it's a bit of a monster. But here is is:
sSQL = "INSERT INTO " & sAudTmpTable & " ( [audType], [audDate], [audUser], [Event_Number], [Event_ID], " & _
"[Received_Date], [Response_Date], [Site], [Server], [Workstation], [Software_Version], [Data_Version], " & _
"[Description], [Test_Description], [Company], [Observed_By], [Observed_Date], [Tested_By], [AssignedTo], " & _
"[Tested_Date], [Test_Result], [Ind_Tested_By], [Ind_Tested_On], [Ind_Test_Result], [Reviewed_By], " & _
"[Actioned_Date], [Review_Date], [Review_Result], [Completed_By], [Completed_Date], [Closed_By], " & _
"[Closed_Date], [Exclude], [Category], [State], [Event_Responsibility], [Probability], [WIP_Number], " & _
"[OriginalWIP], [Severity], [Blocked], [Block_Description], [Tags], [Work], [TaskID], [EventType], " & _
"[DefectType], [known_issue_impact], [known_issue_description], [Operator_Notes], [BugWIP], " & _
"[SupplierName], [SupplierCompany], [Simulator], [ATSTest], [FixPriority] ) " & _
"SELECT '" & EditOrInsert & "' AS Expr1, '" & DateTime & "', '" & User & "', [Event_Number], [Event_ID], " & _
"[Received_Date], [Response_Date], [Site], [Server], [Workstation], [Software_Version], [Data_Version], " & _
"[Description], [Test_Description], [Company], [Observed_By], [Observed_Date], [Tested_By], [AssignedTo], " & _
"[Tested_Date], [Test_Result], [Ind_Tested_By], [Ind_Tested_On], [Ind_Test_Result], [Reviewed_By], " & _
"[Actioned_Date], [Review_Date], [Review_Result], [Completed_By], [Completed_Date], [Closed_By], " & _
"[Closed_Date], [Exclude], [Category], [State], [Event_Responsibility], [Probability], [WIP_Number], " & _
"[OriginalWIP], [Severity], [Blocked], [Block_Description], [Tags], [Work], [TaskID], [EventType], " & _
"[DefectType], [known_issue_impact], [known_issue_description], [Operator_Notes], [BugWIP], " & _
"[SupplierName], [SupplierCompany], [Simulator], [ATSTest], [FixPriority] " & _
"FROM [" & sTable & "] WHERE ((" & sKeyField & ")=" & lngKeyValue & ");"
You reported this attempt fails ...
CurrentProject.Connection.Execute sSQL
... but this works using the same sSQL statement ...
CurrentDb.Execute sSQL, dbFailOnError + dbSeeChanges
CurrentProject.Connection.Execute is an ADO method. CurrentDb.Execute is a DAO method. The two methods are similar, but not the same.
One important difference is the ADO version is more likely to fail when the SQL statement includes reserved words as object (table, field, etc.) names; DAO is more forgiving about problem names.
But there are other differences, and it is not possible to determine which of them was the key factor for an INSERT statement we haven't seen. ;-)