sql - 如何跳过插入 db2 中的错误行?

标签 sql db2 procedure

我真的需要你的帮助。我的情况如下: 我试图在表中插入地理空间数据,但有一些多边形未关闭并给出错误。当错误发生时,它会取消插入并且不插入任何行。我想实现一个程序,跳过有错误的行并插入正确的行。

我正在使用 db2 数据库。 这是我正在处理的最后一个代码:

CREATE OR REPLACE PROCEDURE DDM.GEOMETRY_TESTE ()
LANGUAGE SQL

BEGIN
    DECLARE CONTINUE HANDLER FOR SQLSTATE '38SSL';
    DECLARE CONTINUE HANDLER FOR SQLSTATE '38SSP';
    BEGIN
        CONTINUE;
    END;

    INSERT INTO ddm.DM_SICAR_GEOMETRY_TESTE (IDGEOSIGAM, ID_ORIGEM, TIPO_AREA, TIPO_COORDENADA, AREA_GEO, COORDENADAS, CENTROIDE, COORDENADAS_WKT, TESTE)
    SELECT  
        b.IDGEOSIGAM
        ,b.ID_ORIGEM
        ,b.TIPO_AREA
        ,b.TIPO_COORDENADA
        ,b.AREA_GEO
        ,db2gse.ST_Point(CONCAT('point(',SUBSTRING(COORDENADAS2,1,LENGTH(b.COORDENADAS2)-2)||')'),1) COORDENADAS
        ,db2gse.ST_centroid(db2gse.ST_Point(CONCAT('point(',SUBSTRING(b.COORDENADAS2,1,LENGTH(b.COORDENADAS2)-2)||')'),1)) CENTROIDE
        ,CASE
            WHEN b.TIPO_COORDENADA = 'Point' THEN CONCAT('POINT(',SUBSTRING(COORDENADAS2,1,LENGTH(COORDENADAS2)-2)||')')
            WHEN b.TIPO_COORDENADA = 'MultiPolygon' THEN CONCAT('MULTIPOLYGON(((',SUBSTRING(COORDENADAS2,1,LENGTH(COORDENADAS2)-2)||')))') 
         END COORDENADAS_WKT
        ,CASE
            WHEN b.TIPO_COORDENADA = 'Point' THEN db2gse.ST_Point(CONCAT('POINT(',SUBSTRING(b.COORDENADAS2,1,LENGTH(b.COORDENADAS2)-2)||')'),1) 
            WHEN b.TIPO_COORDENADA = 'MultiPolygon' THEN db2gse.ST_MultiPolygon(CONCAT('MULTIPOLYGON(((',SUBSTRING(b.COORDENADAS2,1,LENGTH(b.COORDENADAS2)-2)||')))'),1)
         END TESTE
    FROM 
        (
        SELECT 
            a.IDGEOSIGAM
            ,a.ID_ORIGEM
            ,a.TIPO_AREA
            ,a.TIPO_COORDENADA
            ,a.AREA_GEO
            ,SUBSTRING(xmlserialize(xmlagg(xmltext(a.LONGLATI) ORDER BY a.ID_ORIGEM, a.IDGEOSIGAM, a.ID_SEQ) as CLOB(1073741824)), 0) COORDENADAS2
        FROM
            (   
            SELECT 
                g.IDGEOSIGAM 
                ,g.ID_ORIGEM 
                ,g.TIPO_AREA
                ,c.TIPO_COORDENADA 
                ,g.AREA_GEO 
                ,c.ID_SEQ 
                ,c.LONGITUDE 
                ,c.LATITUDE 
                ,CONCAT(c.LATITUDE||' '||c.LONGITUDE,', ') LONGLATI
            FROM 
                ddm.DM_SICAR_GEO g
                INNER JOIN ddm.DM_SICAR_GEO_COORDENADAS c ON c.ID_ORIGEM = g.ID_ORIGEM AND c.IDGEOSIGAM = g.IDGEOSIGAM 
            WHERE 
                g.IDGEOSIGAM in (3274, 49069, 63397, 20224, 20222) 
                --g.ID_ORIGEM = 478
            ORDER BY 
                g.ID_ORIGEM
                ,g.IDGEOSIGAM
                ,c.ID_SEQ 
            ) a
        GROUP BY
            a.IDGEOSIGAM
            ,a.ID_ORIGEM
            ,a.TIPO_AREA
            ,a.TIPO_COORDENADA
            ,a.AREA_GEO
        ) b;
END

最佳答案

解决此类问题的最佳方法可能是为自己创建一些 UDF 来包装导致错误的函数(或隐式转换)。例如。你可以用这个

/*
 * Runs ST_MULTIPOLYGON but will return NULL if the function errors out with GSE3421N  Polygon is not closed."
 */

CREATE OR REPLACE FUNCTION DB_MULTIPOLYGON(i CLOB(2G), srs_id INT DEFAULT 4326)
RETURNS db2gse.ST_MULTIPOLYGON
    NO EXTERNAL ACTION
    DETERMINISTIC
BEGIN 
  DECLARE NOT_VALID CONDITION FOR SQLSTATE '38H15';
  DECLARE EXIT HANDLER FOR NOT_VALID RETURN NULL;
  --
  RETURN db2gse.ST_MULTIPOLYGON(I, SRS_ID );
END

然后,如果将 ST_MULTIPOLYGON 的任何调用更改为 DB_MULTIPOLYGON,如果多边形未闭合,您将得到 NULL

db2 -x "values ST_MultiPolygon ('multipolygon (( (3 3, 4 6, 5 3,    3 5) ))', 1)"

会给

SQL20571N  An error occurred in a spatial routine: "GSE3421N  
  Polygon is not closed.".  SQLSTATE=38H15

但是这个

db2 -x "values DB_MultiPolygon ('multipolygon (( (3 3, 4 6, 5 3, 3 5) ))', 1)" 

将返回NULL,然后您可以选择插入或使用WHERE过滤掉它

关于sql - 如何跳过插入 db2 中的错误行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65815083/

相关文章:

mysql - 如何删除表的所有外键

mysql - 制作分数表(难)

sql - 在表格中添加行作为其他行的总和

hadoop - Sqoop:-hbase-row-key 作为值

mysql - MySql中有递归存储过程吗?

mysql - sql - 查询所需数据的更好方法

php - SQL舍入非十进制数

sql - 将多个表连接到桥接表,同时保留两侧数据(包括 NULL)

db2 - Spring Batch ResultSet 在获取所有数据之前被其他人关闭

java - Hibernate 5 创建 ID 未标记为 IDENTITY 的表