代码之家  ›  专栏  ›  技术社区  ›  JULIAN DAVID BECERRA RODRIGUEZ

从MySQL/Go表获取行数据

  •  0
  • JULIAN DAVID BECERRA RODRIGUEZ  · 技术社区  · 1 年前

    首先,它读取代码,以便您理解它的操作逻辑,当运行我捕获它的存储过程时,它会给我带来一个表,其中包含我必须返回的数据,列的名称确实给我带来了它,但列的数据没有给我带来任何东西,我无法创建模型,存储过程的响应有n个列,有n个不同的名称,但列在具有int数据和字符串数据方面各不相同,我需要您从列中捕获正确的数据,因为一切都正常,但列中的数据不正常:

    package controllers
    
    import (
        "database/sql"
        "encoding/json"
        "fmt"
        "net/http"
    
        "github.com/gin-gonic/gin"
    )
    
    type RequestData struct {
        FromData map[string]interface{} `json:"fromData"`
        Call     string                 `json:"Call"`
    }
    
    func HandleDatos(c *gin.Context) {
        var requestData RequestData
    
        if err := c.ShouldBindJSON(&requestData); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
    
        fmt.Printf("Ejecutando procedimiento almacenado: CALL %s\n", requestData.Call)
        fmt.Printf("Parámetros: %v\n", requestData.FromData)
    
        var rows *sql.Rows
        var err error
    
        // Verifica si FromData contiene valores
        if len(requestData.FromData) > 0 {
            // Si hay valores en FromData, crea una consulta con parámetros
            query := "CALL " + requestData.Call + "("
            params := []interface{}{}
            for _, value := range requestData.FromData {
                query += "?, "
                params = append(params, value)
            }
            query = query[:len(query)-2] + ")"
    
            rows, err = db.Raw(query, params...).Rows()
        } else {
            // Si no hay valores en FromData, ejecuta el procedimiento almacenado sin parámetros
            rows, err = db.Raw("CALL " + requestData.Call).Rows()
        }
    
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        defer rows.Close()
    
        // Convierte los resultados en un mapa
        result := make(map[string]interface{})
        columns, err := rows.Columns()
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        fmt.Printf("Columnas: %v\n", columns) // Punto de impresión
    
        data := [][]interface{}{} // Almacena los datos de filas
        for rows.Next() {
            values := make([]interface{}, len(columns))
            for i := range columns {
                values[i] = new(interface{})
            }
    
            if err := rows.Scan(values...); err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
                return
            }
    
            fmt.Printf("Valores escaneados: %v\n", values) // Punto de impresión
    
            row := make(map[string]interface{})
            for i, col := range columns {
                val := *(values[i].(*interface{}))
                row[col] = val
            }
    
            fmt.Printf("Fila escaneada: %v\n", row) // Punto de impresión
    
            // Agrega esta fila al resultado
            data = append(data, values)
        }
    
        fmt.Printf("Datos finales: %v\n", data) // Punto de impresión
    
        if len(data) > 0 {
            result["columns"] = columns
            result["data"] = data
        } else {
            // Si no hay datos, establece un mensaje personalizado
            result["message"] = "Sin datos"
        }
    
        // Convierte el resultado en JSON y devuelve la respuesta
        responseJSON, err := json.Marshal(result)
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        c.JSON(http.StatusOK, string(responseJSON))
    }
    

    这就是它返回给我的内容,它说“列”:[“idPunto”,“nombre”]这部分还可以,但包含数据的行不是我所期望的:

    respuesta dela api al correrla

    1 回复  |  直到 1 年前
        1
  •  0
  •   Adrian Maxwell    1 年前

    将行扫描到接口{}中不会自动将SQL类型转换为Go类型。相反,使用ColumnTypes方法将获得每列的数据类型,从而允许动态分配正确的Go类型。(以下内容未经测试,仅供参考。)

    for i := range columns {
        // Use the column types to determine the appropriate scan type
        switch columnTypes[i].DatabaseTypeName() {
        case "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
            scanArgs[i] = new(int64)
        default:
            scanArgs[i] = new(string)
        }
    
        values[i] = scanArgs[i]
    }
    

    在脚本中:

    package controllers
    
    import (
        "database/sql"
        "encoding/json"
        "fmt"
        "net/http"
    
        "github.com/gin-gonic/gin"
    )
    
    type RequestData struct {
        FromData map[string]interface{} `json:"fromData"`
        Call     string                 `json:"Call"`
    }
    
    func HandleDatos(c *gin.Context) {
        var requestData RequestData
    
        if err := c.ShouldBindJSON(&requestData); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
    
        fmt.Printf("Ejecutando procedimiento almacenado: CALL %s\n", requestData.Call)
        fmt.Printf("Parámetros: %v\n", requestData.FromData)
    
        var rows *sql.Rows
        var err error
    
        // Verifica si FromData contiene valores
        if len(requestData.FromData) > 0 {
            // Si hay valores en FromData, crea una consulta con parámetros
            query := "CALL " + requestData.Call + "("
            params := []interface{}{}
            for _, value := range requestData.FromData {
                query += "?, "
                params = append(params, value)
            }
            query = query[:len(query)-2] + ")"
    
            rows, err = db.Raw(query, params...).Rows()
        } else {
            // Si no hay valores en FromData, ejecuta el procedimiento almacenado sin parámetros
            rows, err = db.Raw("CALL " + requestData.Call).Rows()
        }
    
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        defer rows.Close()
    
        // Convierte los resultados en un mapa
        result := make(map[string]interface{})
        columns, err := rows.Columns()
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        fmt.Printf("Columnas: %v\n", columns) // Punto de impresión
    
        data := []map[string]interface{}{} // Almacena los datos de filas
    
        // Get the column types
        columnTypes, err := rows.ColumnTypes()
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        for rows.Next() {
            values := make([]interface{}, len(columns)
            scanArgs := make([]interface{}, len(columns))
    
            for i := range columns {
                // Use the column types to determine the appropriate scan type
                switch columnTypes[i].DatabaseTypeName() {
                case "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
                    scanArgs[i] = new(int64)
                default:
                    scanArgs[i] = new(string)
                }
    
                values[i] = scanArgs[i]
            }
    
            if err := rows.Scan(values...); err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
                return
            }
    
            fmt.Printf("Valores escaneados: %v\n", values) // Punto de impresión
    
            row := make(map[string]interface{})
            for i, col := range columns {
                // Cast the scanned values to the appropriate data types
                switch columnTypes[i].DatabaseTypeName() {
                case "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
                    row[col] = *(scanArgs[i].(*int64))
                default:
                    row[col] = *(scanArgs[i].(*string))
                }
            }
    
            fmt.Printf("Fila escaneada: %v\n", row) // Punto de impresión
    
            // Agrega esta fila al resultado
            data = append(data, row)
        }
    
        fmt.Printf("Datos finales: %v\n", data) // Punto de impresión
    
        if len(data) > 0 {
            result["columns"] = columns
            result["data"] = data
        } else {
            // Si no hay datos, establece un mensaje personalizado
            result["message"] = "Sin datos"
        }
    
        // Convierte el resultado en JSON y devuelve la respuesta
        responseJSON, err := json.Marshal(result)
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        c.JSON(http.StatusOK, string(responseJSON))
    }
    

    nb:您应该能够将此逻辑扩展到可能遇到的其他数据类型。