I'm trying to ascertain the best way to test for blank/empty/null text records.
By this I mean text records which are either:
Null
An Empty String ("")
Any number of spaces (e.g. " ")
I've experimented with varying query criteria using the following table (named Table1):
Here, the Spaces record contains an arbitrary number number of spaces, the Empty String record contains an empty string (""), and the Null record is just that.
My first thought to achieve my goal was to use a query such as:
SELECT * FROM Table1 WHERE TextField IS NULL OR Trim(TextField)=""
And this indeed returns the three target records: Spaces, Empty String & Null.
However somewhat oddly, using:
SELECT * FROM Table1 WHERE TextField = ""
Returns both the Empty String record and the Spaces record:
Which leads me to think that my query can omit the Trim function and become:
SELECT * FROM Table1 WHERE TextField IS NULL OR TextField=""
But is this reliable?
Is this best practice when selecting empty text records?
Alternatively I considered using:
SELECT * FROM Table1 WHERE Nz(TextField)=""
Are there drawbacks to this approach?
Are there better ways to achieve this?
EDIT: To be specific, my question is ultimately:
What is the best way to select blank text records?
For normal text, Access handles strings with only spaces as empty strings (e.g. SELECT " " = "" returns -1 = True).
This means that the solution introduced by June7, WHERE TextField & "" = "", is likely the most efficient solution. Another contender is the Nz function, which is handled by the database engine and somewhat optimized.
When using indexes, however, both string concatenation and function calls invalidate the index. WHERE TextField IS NULL OR TextField="" doesn't, and will be the fastest by far if TextField is indexed.
If you bring rich text into the mix, you're not going to get away with anything but casting it to normal text first. In Access 2016, when you enter a space in a rich text field, it actually contains the following: <div> </div> (you can see this by using RichTextField & "").
For a rich text field, indexes are not going to work anyway, so you can use the following:
WHERE PlainText(RichTextField) & "" = ""
Nz(TextField)=""
Is the approach most often used when dealing with nulls and empty strings.
In Access, The Long Text data type will automatically be trimmed to save space, this is why Trim(TextField) is the same as TextField. If you ever convert it to a Rich Text data type, these will be different. In that case:
TRIM(Nz(TextField))=""
Should cover all your bases.
Related
I use full text indexing to find results faster and it works well except when the term i search for is attached to an underscore inside the database record.
My database records:
article.title
++++++++++++++++++++++++++++++
My article 123456 created
------------------------------
My article new_123456 created
------------------------------
My article 123456_new created
My match against query:
MATCH(article.title) AGAINST ( "123456*" IN BOOLEAN MODE )
This query return only the first record and ignore the others since the term "123456" is attached to an underscore ( _ ), either before or after the term, the query will ignore the records.
What is the thing I did wrong and how to fix this problem?
There are many things that can mess up FULLTEXT:
Punctuation
"stop words"
min word "length"
Language
It is sometimes best to edit the data before storing it. In your case, replacing "_" with " " might be the 'right' solution. That could be done either in your application code as you insert strings, or by using MySQL's REPLACE() as the string is INSERTed.
I have the following strings:
SDZ420-1241242,
AS42-9639263,
SPF3-2352353
I want to "escape" the SDZ420- part while searching and only search using the last digits, so far I've tried RLIKE '^[a-zA-Z\d-]' which works but I am confused on how to add the next digits (user input, say 1241242) to it. I cannot use LIKE '%$input' since that would return a row even if I just input '242' as the search string.
In simple words, a user input of '1241242' should return the row with 'SDZ420-1241242'. Is there any other approach other than creating a separate table with the numbers only?
Note that without jumping through some crazy hoops, this search needs to hit every row in the table; if you have an index on this, it's not going to use that (an index is generally used, assuming it's of the proper kind, which they tend to be, when you search on start, and generally only when using LIKE 'needle%' and not RLIKE. If that's a problem, storing the digits separately, and then putting an index on that, is probably the simplest way to solve your problem here.
To query for the final few digits, why not:
SELECT * FROM foo WHERE colName LIKE ?
with the string made in your programming language via:
String searchTerm = "%-" + digits;
You can also pass in the number as a string and use:
where substring_index(colname, '-', -1) = ?
This does not require changing the value in the application code.
I have a string that denotes which users are allowed to access something. For instance, if user 1, user 2, and user 3 could access it, the accessibility column would contain 1,2,3. If only user 1 could access it, it would only be 1 and so forth.
I know I can't do a simple CONTAINS clause because searching for 1 could return true for 14,2,3. How would I get a regex to accommodate when there is a comma on both sides, on one side, or neither of the ID number?
Here is a sample of what I'm trying to do
DataID: 1
Accessibility: "1,2,3,4,5"
Data: "secret stuff"
DataID: 2
Accessibility: "5,6,7,8,9"
Data: "more secret stuff"
I need to tell the regex to search for a number and to make sure its at the beginning of the string and the end of the string if it has no commas around it, is at the beginning of the string if it only has a comma after it, is at the end of a string if it only has a comma before it, or if it commas on both sides that's fine because it's in the middle of the string.
I know what I need to do, but don't know how to achieve it. Thanks.
First, you have a really bad data structure for several reasons:
The proper way to store lists in SQL is using tables, not strings.
The proper way to store integers in SQL is as integers, not strings.
Ids should be defined with a proper foreign key relationship, which you cannot do when the id is stored in a string.
Sometimes, we are stuck with other people's bad design decisions. That is, we are unable to create a proper junction table, with one column for the DataId and each user who has access to it.
In that situation, you can use the find_in_set() functionality in MySQL. This does not require a regular expression. You can just write:
where find_in_set($user, accessibility) > 0
Since A-Z, 0-9, and underscore are considered word boundaries, you could generalize like this:
-- word-bound DataID, e.g. 1 becomes \b1\b
SELECT '\b' || DataID || '\b' AS DataID_Bound FROM USER
WHERE REGEX_LIKE(DataID_Bound, Accessibility)
That way it doesn't matter if there is a comma leading, trailing, or if it's a sole occupant of the search subject. But it deffinitely cannot match 14 or 21, etc. \b1\b will only match solo 1, \b14\b will only match whole word 14, etc.
The database I'm working on has a field in one table as a text whereas the other table has the field in a number format. I cannot change the field format at all in the database. Therefore I need to know how to convert the field from text to number before linking (or join) the tables to pull the data.
SELECT DISTINCT tblCoachingDB.ID, tblCoachingDB.SourceId, tblCoachingDBSource.ID
FROM tblCoachingDB, tblCoachingDBSource
WHERE (((tblCoachingDB.SourceId)="12"));
The tblCoachingDB.SourceID is a TEXT whereas the tblCoachingDBSource.ID is a NUMBER
You can use CStr() to cast a number as text and JOIN that to another text field.
SELECT DISTINCT
tblCoachingDB.ID,
tblCoachingDB.SourceId,
tblCoachingDBSource.ID
FROM
tblCoachingDB INNER JOIN tblCoachingDBSource
ON tblCoachingDB.SourceId = CStr(tblCoachingDBSource.ID)
WHERE tblCoachingDB.SourceId='12';
Actually I would leave out the WHERE clause until after you confirm the JOIN works properly.
You originally asked to JOIN by converting the text field to number. I first suggested text instead because I recall Access was less likely to object. But my memory about that is shaky, and if you want numeric for both sides of the JOIN, see which of these (if any) works best for you:
ON Int(tblCoachingDB.SourceId) = tblCoachingDBSource.ID
ON CLng(tblCoachingDB.SourceId) = tblCoachingDBSource.ID
ON Val(tblCoachingDB.SourceId) = tblCoachingDBSource.ID
Note I offered this suggestion only because you told us you are not permitted to alter your tblCoachingDB table's design to make SourceId numeric instead of text datatype. Since you can't make that change, you will have to live with the run-time performance impact of converting the datatype of a JOIN field. That is not a good thing, but I don't know how bad it will be. Good luck.
Assuming that all values in tblCoachingDB.SourceID are numbers, you could create a query, selecting all fields from tblCoachingDB EXCEPT SourceID. Then add a new field to the query SourceID: clng(tblCoachingDB.SourceID)
You would then use the query instead of tblCoachingDB anywhere you needed to make the join. A second alternative would be to create a query for tblCoachingDBSource and using SourceID: cstr(tblCoaching.SourceID) A third alternative would be:
SELECT * FROM tblCoachingDB, tblCoachingDBSource
WHERE (clng(tblCoachingDB.SourceId)=tblCoachingDBSource.ID
AND ((tblCoachingDB.SourceId)="12"));
I'm using Access 2000 and I have a query like this:
SELECT function(field1) AS Results FROM mytable;
I need to export the results as a text file.
The problem is:
function(field1) returns a fairly long string (more than 255 char) that cannot be entirely stored in the Results field created from this query.
When i export this query as a text file, i can't see the string entirely. (truncated)
Is it possible to cast function(field1) so it returns a Memo type field containing the string ?
Something like this:
SELECT (MEMO)function(field1) AS Results FROM mytable;
Do you know others solutions?
There is an official microsoft support page on this problem:
ACC2000: Exported Query Expression Truncated at 255 Characters
They recommend that you append the expression data to a table that has a memo field, and export it from there. It's kinda an ugly solution, but you cannot cast parameters to types in MS Access, so it might be the best option available.
i don't know how to do quite what you're hoping (which makes sense) but a possible alternative could be to create 2 or 3 fields (or separate queries) and extract different portions of the text into each then concat after retrieved.
pseudo: concat((chars 1-255) & (chars 256-510) & (chars 511-etc...))
edit: it's odd that a string longer than 255 is stored but it's not memo. what's up there? another alternative, if you have access to the db, is change the field type. (backup the db first!)