B4J Question Query that returns only the column names that have never been evaluated

amorosik

Expert
Licensed User
I need a query that returns, given the name of a table in the db, all the names of the fields that have never been filled in any row of the data present
Basically the fields I could also delete because at the moment they don't contain any information
How to make a unique query that spits out the above?
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
I don't understand, I've been facing your query for half an hour and I can't figure out where the problem is

SELECT name FROM PRAGMA_TABLE_INFO('AAA_TEST_NULL') WHERE name IN (SELECT name FROM AAA_TEST_NULL WHERE name IS NULL)

I tried the subquery and it returns seven rows correctly
How come it doesn't work?
(I'm using SqlLite-gui latest version)
Me too. It seems that the second query doesn't use the field names obtained from the first one, but I think if it does the second select should throw an exception, show an error message.

However, this can be solved by executing the two select-queries separately and with some code; is this a problem?
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
What do you mean?
If it can't be done, then find another way
Voglio dire: sei obbligato a farlo con un'unica query? Non PUOI scrivere codice B4X? Perché la soluzione, con 2 query e poche righe di codice, c'è.

I mean: are you forced to do that using a single query? Can't you write B4X code? There is a solution, with 2 queries and a few lines of code.
 
Upvote 0

amorosik

Expert
Licensed User
Voglio dire: sei obbligato a farlo con un'unica query? Non PUOI scrivere codice B4X? Perché la soluzione, con 2 query e poche righe di codice, c'è.

I mean: are you forced to do that using a single query? Can't you write B4X code? There is a solution, with 2 queries and a few lines of code.

Building a query scrolling through the fields of a table is a procedure I already have and it works
But being slow I wanted to improve it and therefore I was trying to understand if with a stroke of sql it was possible to have the names of the fields inciminated
But in one way or another it seems not so easy
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
B4X:
Public Sub OnlyNullFieldNames(TableName As String) As List
    Dim lstFieldNames As List
    lstFieldNames.Initialize
    Dim lstFieldNamesWithNull As List
    lstFieldNamesWithNull.Initialize

    Dim Query As String

    Query = $"SELECT name FROM PRAGMA_TABLE_INFO('${TableName}')"$

    'Get the table field names.
    Dim RS As ResultSet
    RS = mDB.ExecQuery(Query)
    Do While RS.NextRow
        lstFieldNames.Add(RS.GetString("name"))
    Loop
    RS.Close
   
    'Count the number of records.
    Query = $"SELECT COUNT(*) FROM '${TableName}'"$
    Dim RecordsCount As Int
    RecordsCount = mDB.ExecQuerySingleResult(Query)
   
    'Search for "full null" fields.
    For Each FieldName As String In lstFieldNames
        Query = $"SELECT Count(*) FROM '${TableName}' WHERE '${FieldName}' IS NULL"$
        Dim Count As Int = mDB.ExecQuerySingleResult(Query)
        If Count = RecordsCount Then
            lstFieldNamesWithNull.Add(FieldName)
        End If
    Next
   
    Return lstFieldNamesWithNull
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
'Search for "full null" fields.
I think you need to change this line by removing the single quotes from:
B4X:
Query = $"SELECT Count(*) FROM '${TableName}' WHERE '${FieldName}' IS NULL"$
to this line for it to woek::
B4X:
Query = $"SELECT Count(*) FROM '${TableName}' WHERE ${FieldName} IS NULL"$
Please note that we took that list of col names with null approach way back in Post #9, but apparently, that is not the approach @amorosik wants to take.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I think you need to change this line by removing the single quotes from:
Yes, I should have used square brackets (although it would be better for the names to have no spaces or worse)

Please note that we took that list of col names with null approach way back in Post #9
I assumed so, having seen various posts (without looking "in depth").

He would like a single query but I still haven't made one that works (not always possible, of course).
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Please note that we took that list of col names with null approach way back in Post #9,
The differences from the source in post #9 are that the one I posted doesn't iterate all fields that might have a Null value and that it works on any table, whose name is passed as a parameter.
The only loop is on the detected field names (we could shorten the source code, without storing the field names in the list and executing the next query inside the previous "Do While", but it's not worth it, the speed of the routine would practically not change while the readability is better that way).
 
Upvote 0

amorosik

Expert
Licensed User
I have try with Sql Server
No name returned
Is the bad query, not a db or a tools

B4X:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'ART_ANA'
AND COLUMN_NAME NOT IN (
    SELECT COLUMN_NAME
    FROM dbo.ART_ANA
    WHERE COLUMN_NAME IS NOT NULL
)
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
I adjusted Luca's code of post 47 and did away with one of the lists to make it work each time. It returns a list of the column names that have all null or empty string in all their rows. I tested it on a table with 3 columns : Stakevalue, Name, Note and it works:
B4X:
Sub OnlyNullFieldNames(TableName As String) As List   
    'Count the number of records in db table
    Dim Query As String   
    Query = $"SELECT COUNT(*) FROM '${TableName}'"$
    Dim RecordsCount As Int
    RecordsCount = SQL.ExecQuerySingleResult(Query)
   
    Dim lstFieldNamesWithNull As List
    lstFieldNamesWithNull.Initialize
    Query = $"SELECT name FROM PRAGMA_TABLE_INFO('${TableName}')"$
    'Get the table field names and iterate over them
    Dim rs As ResultSet
    rs = SQL.ExecQuery(Query)
    Do While rs.NextRow
        Query = $"SELECT Count(*) FROM '${TableName}' WHERE ${rs.GetString("name")} IS NULL OR ${rs.GetString("name")} ='' "$
        Dim Count As Int = SQL.ExecQuerySingleResult(Query)
        If Count = RecordsCount Then
            lstFieldNamesWithNull.Add(rs.GetString("name"))           
        End If
    Loop
    rs.Close  
    Return lstFieldNamesWithNull
End Sub
I think you can take it to the bank.
The list shows both Name and Note cols in this table test:
Stakevalue,Name,Note
1,Null,Null
1000,Null,""
2000,Null,Null
509,"",Null
45,Null,,""
I also tested on the OP below table and it worked:
1683287183412.png
 
Last edited:
Upvote 0

aeric

Expert
Licensed User
Longtime User
Maybe this is not what you wanted.
I can create Triggers for (INSERT, UPDATE, DELETE) to add the field names into a CHECKING table and I can query them after I have executed an action such as INSERT, UPDATE, DELETE.
 

Attachments

  • Customers.zip
    792 bytes · Views: 51
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Ok, but WHY the single query is not return any name?
You don't need the single quote. If you use the code sub I have in post #52, it will work for you every time. To see which columns have all NULL or empty string, do this:
B4X:
For Each f As String In OnlyNullFieldNames("AAA_TEST_NULL")
    Log($"Cols with all NULL/empty rows: ${f}"$)
Next
If you are using B4J make sure you have a lot more recent jar file than this: #AdditionalJar: sqlite-jdbc-3.7.2
I use this one, but you may have to download it to your additional B4J folder: #AdditionalJar: sqlite-jdbc-3.36.0.3.
If you have problems, I can upload you a project using your database. I can make it work in B4A and B4J.
 
Upvote 0

amorosik

Expert
Licensed User
Have patience but what I need I know very well by myself
I already have code that lets me know which fields have never been used
I don't need to have another routine do the same thing
What I need is to understand why the single query, for example like in post#51, doesn't return the field names as I would expect
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Have patience but what I need I know very well by myself
I already have code that lets me know which fields have never been used
I don't need to have another routine do the same thing
What I need is to understand why the single query, for example like in post#51, doesn't return the field names as I would expect
This is an easy question.
Answer: The table dbo.ART_ANA doesn't contain a column with name COLUMN_NAME.
 
Upvote 0

amorosik

Expert
Licensed User
This is an easy question.
Answer: The table dbo.ART_ANA doesn't contain a column with name COLUMN_NAME.

COLUMN_NAME is present on the principal query is a field name on INFORMATION_SCHEMA.COLUMNS
The content of COLUMN_NAME (the current column name) is then passed to the subquery
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
COLUMN_NAME is present on the principal query is a field name on INFORMATION_SCHEMA.COLUMNS
The content of COLUMN_NAME (the current column name) is then passed to the subquery
How about this SQLite statement which involves 2 simple queries like this without lists and without variables. I just cannot see it done using one simple query the way you want. This is my final answer:
B4X:
Dim rs1 As ResultSet =SQL.ExecQuery($"Select name
    FROM PRAGMA_TABLE_INFO('AAA_TEST_NULL') "$)    
    Do While rs1.nextrow
        Dim rs2 As ResultSet= SQL.Execquery($"SELECT DISTINCT ${rs1.getstring("name")} FROM AAA_TEST_NULL
        WHERE ${rs1.getstring("name")} IS NULL
        OR ${rs1.getstring("name")} = ''
        "$)
        Do While rs2.NextRow
            Log(rs1.getstring("name"))
        Loop
        rs2.Close
    Loop
    rs1.Close
If this is your table, it will show you: prezzo
1683391488765.png
 
Upvote 0
Top