I want to write an SQL query using MS access, which calculates a serial number using a VBA Function.
I have a big "samplebasicinformation" table which has lots of foreign keys and want to use the text fields in the foreign tables to create a text-based serial number.
I want the first field of the query to abbreviate a few text fields from other tables, then concatenate them and create this serial number.
In order to abbreviate the text fields I have the following function:
Function GetFirstLetters(rng As String)
Dim arr
Dim I As Long
arr = VBA.Split(rng, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
GetFirstLetters = GetFirstLetters & Left(arr(I), 1)
Next I
Else
GetFirstLetters = Left(arr, 1)
End If
End Function
I've tried the below SQL to achieve this but failed due to syntax error.
SELECT
(getfirstletters(select sl.locationname from samplebasicinformation as sbi join samplelocation as sl
on sbi.samplelocationid = sl.samplelocationid)),
samplebasicinformationid
from samplebasicinformation as sbi1
Would anyone be able to offer some advice?
You need to feed a single column to your function.
Your query is rather confusing, I think it is as simple as this:
SELECT
getfirstletters(sl.locationname),
sbi.samplebasicinformationid
FROM samplebasicinformation as sbi
INNER JOIN samplelocation as sl
on sbi.samplelocationid = sl.samplelocationid
Note that you need INNER JOIN in Access Sql.
Related
I have a question about using LINQ to access a Database and trying to make use of it's version of accessing the LIKE comparison operator.
I know that LINQ has .Contains(), .StartsWith(), and .EndsWith() as comparison methods. However I am wondering if there is a way to programatically imcorporate SQL Wildcards into a LINQ statement without explicitly using these query operators. Let me explain my situation.
I am writing a program that accesses a database, and part of the program is a search window which the user can use to help them find specific database data. I would like to try and incorporate SQL Wildcards into the textbox fields for these search pages.
For example if a user enters the input 17% I'd want the program to check for anything in that specific column that starts with a 17. The same is true with %17 and 17 where I'd want it to search for columns that end with, and contain the values.
Currently, this is the code I have for my search method:
Public Function Data_Search(sData As List(Of String), DB As CustomDataContext) As DataGridView
Dim gridData As New DataGridView
Dim query = From p In DB.Parts
Select p.Part_Number, p.Part_Description, p.Supplier.Supplier_Name
for i = 0 To sData.Count - 1
If Not sData(i).ToString() = "" Then
Select Case i
Case 0
Dim partNum As String = sData(i).ToString()
query = query.Where(Function(x) x.Part_Number.Contains(partNum))
Case 1
Dim description As String = sData(i).ToString()
query = query.Where(Function(x) x.Part_Description.Contains(description))
Case 2
Dim supp As String = sData(i).ToString()
query = query.Where(Function(x) x.Supplier_Name.Contains(supp))
End Select
End If
Next
gridData.DataSource = query.ToList()
Return gridData
End Function
So right now I am trying to see if there is a way for me to modify the code in a way that doesn't essentially involve me putting a substring search into each Case section to determine if I should be using StartsWith(), Contains(), or EndsWith.
Thanks for your time.
If you are using LINQ to SQL, and you are talking to Microsoft SQL Server, then you can use SQLMethods.Like to implement SQL LIKE:
query = query.Where(Function(x) SQLMethods.Like(x.Part_Number, partNum))
I have the following two queries that take information from the same table
I need to compare the two tables and find all the information that's value is different. Is there any way to do this without having to make a loop?
Dim housepress = (From press In db.PressInfo
Where press.PressName = pressname And press.CustomerID = "House"
Select press).ToList()
Dim curpress = (From press In db.PressInfo
Where press.PressName = pressname And press.CustomerID = Customername
Select press)
I tried using curpress.Except but I get an error that "Local sequence cannot be used in Linq to SQL
We have a fairly large Oracle database that we are able to connect via Microsoft Access and ODBC with read-only access. We work with a front-end system that does not match the structure behind the scenes and often I need to query the system via Microsoft Access. The problem is that we are not provided any documentation as to structure and the structure needs serious attention. Searching for the field that I need is very time consuming.
With our front end, I'm able to view the values that I want to query, and I know the key fields, but I need to find the field that contains the known value.
If I have a record where I know the value of field "A", and have the value of field "X", is it possible to query field "X"?
Front end shows
Student ID: 12345678
Payments: 23456
Back end
TechID: 12345678
???: 23456
Can I query "???"
You can do this by iterating over the collection of tables, and for each table, the collection of fields.
Open Database
Get all Tables
For Each Table
Get all Fields
For Each Field
If Field type is text ... and
If Field size is not TOO Long ...
Search for string
If found, write to a results bucket
Next
Next
Here is an example of code for cataloging tables (source here)
Public Function GenerateDataDictionary(aDataDictionaryTable As String)
'*** Usage: GenerateDataDictionary("MyDataDictionaryTable")
'*** Extracts the information about the tables for the data dictionary
'*** and inserts it to a table named aDataDictionaryTable
Dim tdf As TableDef, fldCur As Field, colTdf As TableDefs
Dim rstDatadict As Recordset
Dim i As Integer, j As Integer, k As Integer
Set rstDatadict = CurrentDb.OpenRecordset(aDataDictionaryTable)
Set colTdf = CurrentDb.TableDefs
'Go through the database and get a tablename
For Each tdf In CurrentDb.TableDefs
'Do what you want with the table names here.
rstDatadict.AddNew
rstDatadict.Update
rstDatadict.AddNew
rstDatadict![Table] = tdf.NAME
rstDatadict![Field] = "----------------------------"
rstDatadict![Display] = "----------------------------"
rstDatadict![Type] = ""
rstDatadict.Update
rstDatadict.AddNew
rstDatadict![Table] = "Table Description:"
For j = 0 To tdf.Properties.Count - 1
If tdf.Properties(j).NAME = "Description" Then
rstDatadict![Field] = tdf.Properties(j).Value
End If
Next j
rstDatadict.Update
rstDatadict.AddNew
rstDatadict.Update
For i = 0 To tdf.Fields.Count - 1
Set fldCur = tdf.Fields(i)
rstDatadict.AddNew
rstDatadict![Table] = tdf.NAME
rstDatadict![Field] = fldCur.NAME
rstDatadict![Size] = fldCur.Size
Select Case fldCur.Type
Case 1
FieldDataType = "Yes/No"
Case 4
FieldDataType = "Number"
Case 8
FieldDataType = "Date"
Case 10
FieldDataType = "String"
Case 11
FieldDataType = "OLE Object"
Case 12
FieldDataType = "Memo"
Case Else ' Other values.
FieldDataType = fldCur.Type
End Select
rstDatadict![Type] = FieldDataType
For j = 0 To tdf.Fields(i).Properties.Count - 1
If fldCur.Properties(j).NAME = "Description" Then
rstDatadict![DESCRIPTION] = fldCur.Properties(j).Value
End If
If fldCur.Properties(j).NAME = "Caption" Then
rstDatadict![Display] = fldCur.Properties(j).Value
End If
If fldCur.Properties(j).NAME = "Rowsource" Then
rstDatadict![LookupSQL] = fldCur.Properties(j).Value
End If
Next j
rstDatadict.Update
Next i
Debug.Print " " & tdf.NAME
Next tdf
End Function
You can catalog your findings in Access by making a table of field-names which joins to a table of table-names. Then your searches are based on the catalog instead of raw collections.
I reverse-engineered the schema for MAS 90 (with JobOps add-in) this way. There's no map, but I had a read-only ODBC connection which I used in precisely the way you propose. The purchasing accountant would give me a distinctive Product Number and I'd run it through this comprehensive engine. Over time I succeeded in distilling 700 tables comprising 18k fields down to 20 tables and a few hundred fields. That allowed us to export our data.
The answer to your question is simple. No, you cannot do that.
There are two solutions that I can think of. The first is to manually concatenate all the values together and then look for the row that contains the value. This is imperfect, but might work:
select *
from (select t.*, ('|'""col1||'|'||col2+'|' . . .||'|') as allcols
from t
) t
where instr('|23456|', allcols) > 0
This would find any row that has that value in a column. Probably close enough for what you want.
The second is to use UNPIVOT to do essentially the same thing.
I would strongly suggest that you invest a little bit of time to find the mapping between the fields, and then create a view in Oracle that has the field names as seen in the application. It sounds like this would save you a lot of effort in the medium term.
I am trying to write some code that uses SQL to delete rows from several tables.
A user would type type numbers into a textbox that are separated by a comma which is used in the WHERE clause of a SQL DELETE statement.
I have managed to split the string into a variant array and now I want to insert it into my SQL statement.
How do I insert the variable into the SQL statement and have it run through every element of the array?
EDIT: A bit more digging has taught me about For Each Next statements. This is probably what im looking for.
I suggest you build your query in VBA, then your list of numbers can be an IN statement:
sSQL = "DELETE FROM table WHERE ID In (" & MyList & ")"
Where MyList = "1,2,3,4" or such like.
As you can see, you do not need an array and a textbox would be more suitable than a combobox. If you wish to allow your users to select by say, a name, then a listbox is useful. You can iterate through the selected items in the listbox and build a string from IDs to be used in the Delete statement. ( MS Access 2007 - Cycling through values in a list box to grab id's for a SQL statement )
You can then execute the sql against an instance of a database. For example:
Dim db As Database
Set db = CurrentDB
db.Execute sSQL, dbFailOnError
MsgBox "You deleted " & db.RecordsAffected & " records."
A generic approach
WHERE
','+Array+',' like '%,'+col+',%'
It will consider all the numbers available in your Array
You could make it simple and elaborate a string, something like
stringBuilder sb = StringBuilder("DELETE FROM YOURTABLE WHERE ");
foreach(string st in stringArray){
sb.append("YOURFIELD='" + st + "'");
//If it is not the last element, add an "OR"
if (st != stringArray[stringArray.length -1]) sb.append(" OR ");
}
//Now, you have a string like
//DELETE FROM YOURTABLE WHERE YOURFIELD='hello' OR YOURFIELD='YES'
//... do something with the command
This method will fail if you want to run SQL query on two (or multiple) columns using array values from two different arrays. .e.g
where col1=array1(i) and col2=array2(i)
I'm now working on vbscript to do some test. Actuelly, I want to retrieve a large amount of data from an oracle database, so I write the code like this:
sql = "Select * from CORE_DB where MC = '" & mstr & "' "
Set myrs = db_execute_query(curConnection, sql)
Then I count the rows in myrs,there are 248 rows. So then I do a For loop to retrieve some fields of each row.
For k = 0 To db_get_rows_count(myrs)
But then I found that the content of the row k when k > 133 was always equal to k = 133. So this makes an error.
The db_execute_query function is like
Function db_execute_query ( byRef curSession , SQL)
set rs = curSession.Execute( SQL )
set db_execute_query = rs
End Function
The db_get_rows_count function is like
Function db_get_rows_count( byRef curRS )
dim rows
rows = 0
db_get_rows_count = rows
curRS.MoveFirst
Do Until curRS.EOF
rows = rows+1
curRS.MoveNext
Loop
db_get_rows_count = rows
End Function
As I think, there may be a limit size of mrys ? Could anyone light me about this? Thanks a lot in advance
It would be useful to know what's actually in the database. Can you connect to your database using some other tool (SQLPlus, PL/SQL Developer, Toad, etc) and execute your query? And if you do so, do the results match those that you get when you execute your query through VBScript?
Also, do you get an error from the database? That might help determine what's going on.