Is Golang's SQL package incapable of ad hoc / exploratory queries?
The sql.Rows
type has a Columns
method that will give you a list of the result column names. That can be used to determine the number of columns for unknown queries.
In the docs for the Scan
method, it says:
If an argument has type *[]byte, Scan saves in that argument a copy of
the corresponding data. The copy is owned by the caller and can be
modified and held indefinitely. The copy can be avoided by using an
argument of type *RawBytes instead; see the documentation for RawBytes
for restrictions on its use.If an argument has type *interface{}, Scan copies the value provided by
the underlying driver without conversion. If the value is of type
[]byte, a copy is made and the caller owns the result.
So we also have support for scanning column values when we don't know their type: either in their raw form, or as Go types.
Putting these two together, you could do something like the following using the ...
syntax to call variadic functions:
columnNames, err := rows.Columns()
if err != nil {
log.Fatalln(err) // or whatever error handling is appropriate
}
columns := make([]interface{}, len(columnNames))
columnPointers := make([]interface{}, len(columnNames))
for i := 0; i < len(columnNames); i++ {
columnPointers[i] = &columns[i]
}
if err := rows.Scan(columnPointers...); err != nil {
log.Fatalln(err)
}
Now the columns
slice should contain the decoded versions of all the column values for the current result row.
If you have extra knowledge about the table (e.g. expected types, or know the number of columns ahead of time), you could probably simplify the logic a little.
Is there a way to get the Type for a Column using package database/sql in golang?
You should be able to do it this way:
func printRows(rows *sql.Rows){
colTypes, err := rows.ColumnTypes()
for _,s := range colTypes {
log.Println("cols type:", s.DatabaseTypeName());
}
}
Scan row into slice
You can do it this way:
cols, err := rows.Columns() // Remember to check err afterwards
vals := make([]interface{}, len(cols))
for i, _ := range cols {
vals[i] = new(string)
}
for rows.Next() {
err = rows.Scan(vals...)
}
on the internet they say you can use:
vals[i] = new(sql.RawBytes)
instead of
vals[i] = new(string)
but I think (string) is fine, idk
Related Topics
MySQL - Select All Except What Is in This Table
SQL Missing Right Parenthesis on Order by Statement
Dynamic SQL Column Value Duplicate and Difference Detection Merge Query
Get Data Type of Field in Select Statement in Oracle
Remove Duplicate Records Except the First Record in SQL
Why Would Year Fail with a Conversion Error from a Date
SQL Server:Get All String Occurences (Tags) from Nvarchar(Max) Variable Containing a JSON String
Select Something That Has More/Less Than X Character
Ukrainian Character Change to Question Mark When Insert to Table
Should I Set Max Pool Size in Database Connection String? What Happens If I Don'T
Find Working Days Based on Weekly or Monthly Schedule
For Each Quarter Between Two Dates, Add Rows Quarter by Quarter in SQL Server
How to Pass a Parameter from Vb.Net
Efficient Implementation of Faceted Search in Relational Databases
Extract Sp and Ddl Scripts in Sybase Server
Why Do I Receive a Mutator Error When Modifying an Xml Value in SQL