Access SQL - Insert records with null fields? - sql

I have Insert statement that inserts records from one table to another. SQL works, but not If field in WHERE clause is Null. No errors, just nothing gets inserted. How can I fix this ? This is what I have (fields are named same in both tables - Me.[Serial_No] represents bound field - textbox :
dim SQL as String
SQL = "INSERT INTO Table1 (Serial_No,Name,Description)" & _
"SELECT Table2.Serial_No, Table2.Name, Table2.Description" & _
" FROM Table2" & _
" WHERE Table2.Serial_No='" & Me.[Serial_No] & "'"
DoCmd.RunSQL SQL

I am not sure if this is the answer you require, it doesn't appear very logical.
If name and description are never null values then ensure that they are a unique composite key in your table. You can create these unique keys in the index button in table design view. Then you could look up the serial_no using the other field values. Seems a bit long winded to me but should give you the record you require.
dim SQL as String
dim varSerialNo as string
varSerialNo = dlookup("Serial_No", "table2", "Name='" & me.Name & "' AND Description='" & me.description & "'")
SQL = "INSERT INTO Table1 (Serial_No,Name,Description)" & _
"SELECT Table2.Serial_No, Table2.Name, Table2.Description" & _
" FROM Table2" & _
" WHERE Table2.Serial_No='" & varSerialNo & "'"
DoCmd.RunSQL SQL

Related

Finding/Marking Duplicate Values using SQL

I am trying to update a column in my table to specify if the record is a duplicate or not. To do this I added a field called 'DuplicateRecord'.
I can't use the query wizard in access as the duplicate option in this only allows for 10 fields to be checked as a duplicate and my table has more than 10 fields.
The below code works for me:
Call Module1.RunSQL("UPDATE myTable " & _
"SET myTable.DuplicateRecord = TRUE " & _
"WHERE myTable.[CompanyID] IN (" & _
"SELECT * FROM " & _
"(SELECT myTable.[CompanyID] " & _
"FROM myTable " & _
"GROUP BY myTable.[CompanyID] " & _
"HAVING COUNT(*) > 1 ) T1 ) ")
However this code just runs off one field and I need it to run off all fields in the table (there are about 15 fields).
As a test I tried using two fields to see if I could get this working using the following:
Call Module1.RunSQL("UPDATE myTable " & _
"SET myTable.DuplicateRecord = TRUE " & _
"WHERE myTable.[CompanyID] AND myTable.[Product] IN (" & _
"SELECT * FROM " & _
"(SELECT myTable.[CompanyID], myTable.[Product], COUNT(*) " & _
"FROM myTable " & _
"GROUP BY myTable.[CompanyID], myTable.[Product] " & _
"HAVING COUNT(*) > 1 ) T1 ) ")
However I get an error message saying "Run-time error '3306' You have written a subquery that can return more than one field without using the EXISTS reserved word in the main query's FROM clause. Revise the SELECT statement of the subquery to request only one field."
I've tried googling the error but I can't seem to solve it as I don't fully understand it.
Does anyone know how I can apply the logic of testing for duplicates? Is there an easier way to do this then how I am currently trying? I will need to do this for the full record (15 fields), so I am a bit conscious that the way I am currently attempting this might not be the best fit.

Searching a table where the field doesnt exist - Access VBA

I am a data consultant who migrates data I am sent into our system. I have written code that compares the contents of my table against what has been put into oracle, as an extra test. The tables are a little convoluted due to how they relate to each other. But essentially here is my question:
When I look to match two field values and the field doesnt exist I get a parameter pop up box. I want to only run the code if the field exists.
I have tried many things, wrapping an if statement around it but I always get the parameter box, can anyone help there must be an easier way to do this!
If Not DoCmd.OpenQuery("SELECT TOP 1" & MatchValues!FieldName & " FROM " &
MatchValues!ORACLE_TABLE_NAME) Then
MsgBox "moomins"
' strSQL = "INSERT INTO 002_TableValueErrors(ORACLE_TABLE_NAME,TRANSFORM_TABLE_NAME,FIELD_NAME,ORACLE_FIELD_VALUE,TRANSFORM_FIELD_VALUE) "
' strSQL = strSQL & " VALUES (" & MatchValues!ORACLE_TABLE_NAME & "," & MatchValues!TRANSFORM_TABLE_NAME & "," & MatchValues!FieldName & ",'ORACLE: NOT FOUND','ORACLE: NOT FOUND')"
End If
If you deal with Oracle: Have you tried to check if the field exists by querying ALL_TAB_COLUMNS in Oracle?
"Select count(*) from ALL_TAB_COLUMNS where table_name = " & MatchValues!ORACLE_TABLE_NAME & " and COLUMN_NAME = " & MatchValues!FieldName
(Untestet cause currently I have no Oracle Instance available)

ACCESS VBA using using one more SQL QUERY in WHERE clause

I have two tables, one is std Table and KeyTable.
I have to display the values of std table based on the condition of keytable.
For example, if the user selects ASIA, i have to create a sql query list of countries in ASIA and use this country values (example: INDIA,SRILANKA,BANGLADESH) as where clause in final query. I have tried building them. But I am not sure of the syntax
First query to filter out the values of ASIA
strSQL1 = "SELECT keytable.[Lead Country] FROM keytable WHERE keytable.country='" & lstcountry & "';"
Second query to display the values according to the first query in where clause
strSQL = "SELECT * FROM [Std Table] WHERE ([Std Table].Country IN (______));
The blank which i am missing.
You could just combine the two queries into one statement:
strSQL= "SELECT * " & _
"FROM [Std Table] " & _
"WHERE [Std Table].Country IN " & _
"(" & _
" SELECT s.[Lead Country] " & _
" FROM keytable AS s WHERE s.country = '" & lstcountry & "' " & _
")"
I'd try
strSQL1 = "SELECT keytable.[Lead Country] FROM keytable WHERE keytable.country='" & lstcountry & "'"
strSQL = "SELECT * FROM [Std Table] WHERE ([Std Table].Country IN (" & strSQL1 & "));"
SQL Server would allow you to do that, I guess that ACCESS supports this, too.
Please note that I removed the ; in strSQL1!
You could also provide a list of comma separated values:
strSQL = "SELECT * FROM [Std Table] WHERE ([Std Table].Country IN ('DE','UK','JP'));"

if exists, update, else insert new record

i am inserting values into a table
if the record exists already replace it, and if it does not exist then add a new one.
so far i have this code:
INSERT INTO table_name
VALUES (value1, value2, value3,...) where pk="some_id";
but i need something like this
if not pk="some_id" exists then INSERT INTO table_name
VALUES (value1, value2, value3,...) where pk="some_id"; else update table_name where pk="some_id"
what would be the correct SQL syntax for this?
please note that i am using sql access and that i guess it can be a combination of vba and sql
First update rows which match between your import table and master table.
UPDATE table_name AS m
INNER JOIN tblImport AS i
ON m.pk = i.pk
SET
m.field2 = i.field2,
m.field3 = i.field3,
m.field4 = i.field4;
Then add any imported records which don't exist in the master table.
INSERT INTO table_name (
pk,
field2,
field3,
field4)
SELECT
i.pk,
i.field2,
i.field3,
i.field4
FROM
tblImport AS i
LEFT JOIN table_name AS m
ON i.pk = m.pk
WHERE
(((m.pk) Is Null));
This could be done easily with recordsets. The code would then look like that (for an ADODB recordset):
myRecordset.find ....
if myRecordset.EOF then
myRecordset.addNew
endif
....
myRecordset.fields(...) = ...
....
myRecordset.update
I have posted about my approach to this problem many, many times in many different forums, but I'll just recapitulate the basic structure of the approach I use. There is no way to do it in one step, though.
update the existing records from the external data source.
insert records that don't already exist.
This assumes a common primary key that can be used to link the existing table with the external data source.
Task #2 is pretty trivial, just an outer join for the records that don't already exist.
One can use brute force for #1, writing an UPDATE statement with a SET for each field other than the primary key, but I consider that to be messy and unnecessary. Also, since I have a lot of replicated applications, I can't do that, as it would result in false conflicts (when a field is updated to the same value as it started with).
So, for that purpose, I use DAO and write an on-the-fly SQL statement to update COLUMN-BY-COLUMN. The basic structure is something like this:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim fld As DAO.Field
Dim strField As String
Dim strSet As String
Dim strWhere As String
Dim strSQL As String
Set db = CurrentDB
Set rs = db.OpenRecordset("DestinationTable")
For Each fld in rs.Fields
strField = fld.Name
If strField <> "PKField" Then
strSet = "DestinationTable." & strField & " = ExternalTable." & strField
strWhere = "Nz(DestinationTable." & strField & ",'') = Nz(ExternalTable." & strField & ", '')"
strSQL = "UPDATE DestinationTable "
strSQL = strSQL & " SET " & strSet
strSQL = strSQL & " WHERE " & strWhere
db.Execute strSQL, dbFailOnError
Debug.Print strField & ": " & db.RecordsAffected
End If
Next fld
Now, the complicated part is handling numeric vs. date vs. string fields, so you have to have some logic to write the WHERE clauses to use proper quotes and other delimiters according to the field type. Rather than test the field type, I generally just use a CASE SELECT like this, making string fields the default:
Dim strValueIfNull As String
Select Case strField
Case "DateField1", "DateField2", "NumericField2", "NumericField2", "NumericField3"
strValueIfNull = "0"
Case Else
strValueIfNull = "''"
strWhere = "Nz(DestinationTable." & strField & ", '') = Nz(ExternalTable." & strField & ", '')"
End Select
strWhere = "Nz(DestinationTable." & strField & ", " & strValueIfNull & ") = Nz(ExternalTable." & strField & ", " & strValueIfNull & ")"
I could have the details there wrong, but you get the idea, I think.
This means you'll run only as many SQL updates as there are updatable fields, and that you'll only update records that need updating. If you're also stamping your records with a "last updated" date, you'd do that in the UPDATE SQL and you'd only want to do that on the records that really had different values.

How to "order by" a column and "Include Column Name with query"?

I am trying to run a sql query in excel and I want to :
1. order the query result by my column "Stationname"
2. include the column names with the query
Right now it is returning all the columns without the column name, and the end users do not know what it is.
Could someone please help? I am stuck! Below is my current code:
strQuery = "select pipelineflow.lciid lciid, ldate, volume, capacity, status, " & _
"pipeline, station, stationname, drn, state, county, owneroperator, companycode, " & _
"pointcode, pointtypeind, flowdirection, pointname, facilitytype, pointlocator, " & _
"pidgridcode from pipelineflow, pipelineproperties " & _
"where pipelineflow.lciid = pipelineproperties.lciid " & _
"and pipelineflow.audit_active = 1 " & _
"and pipelineproperties.audit_active =1 " &
_
"and pipelineflow.ldate " & dtInDate & _
"and pipelineproperties.stationname = '" & Stationname & "' "
For part 1 of your question, add an ORDER BY clause to your query. In this case: order by stationname
Part 2: Not sure why column names aren't being included in your query. You can explicitly name a column using something like the following (purely an example):
select mycolumn as "MyCustomizedColumnName" from mytable
That allows you to give columns names of your choosing. Having said that, you shouldn't be required to do so for every column, so I suspect something else is going on in your case.
I should probably add that a stored procedure (rather than dynamic SQL) will yield better runtime performance.
For ordering just put
Order By stationname
at the end of the Query.
You can iterate through the column names by using:
rst(1).Name
where rst is your recordset, and the number is the index of the column.
To sort your query results , use 'ORDER BY' at the end of the query. The last lines of your query would look like this
"and pipelineproperties.stationname = '" & Stationname & "' " & _
"ORDER BY pipelineproperties.stationname"
The column heading are returned in your query data, but not automatically written to the Excel worksheet. The code snippet below shows how to loop through the recordset's column headings and write them to the active cell's row.
'rst' refers to your recordset, update the name as required.
If Not rst.EOF Then
For x = 0 To rst.Fields.Count - 1
With ActiveCell.Offset(0, lcount)
.Value = rst.Fields(x).Name
End With
Next
End If
Make sure that you offset down from the active cell when writing the query results to the worksheet, otherwise your headings will be overwritten by the data.
Activecell.Offset(1,0).CopyFromRecordset rst