【问题标题】:Replace all instances in a string替换字符串中的所有实例
【发布时间】:2021-08-16 19:51:12
【问题描述】:

我有下面的 Snowflake Javascript 存储过程,我需要在 sql 语句中替换字符串的多个实例。

 CREATE OR REPLACE PROCEDURE MYSCHEMA.CountryDelete(COUNTRY VARCHAR) 
    RETURNS string
    LANGUAGE JAVASCRIPT
    AS
    $$
        var error_msg = 'Success';      
        try 
        {
            var sql_cmd_temp = `DELETE FROM MYSCHEMA.CountryTable_{country} 
            WHERE COUNTRY_CODE = '{country}';`  
            var sql_cmd = sql_cmd_temp.replace("{country}", COUNTRY);       
            return sql_cmd;   
        }
        catch(err) 
        {
            error_msg += "ERROR : " + err.message;
        }
        return sql_cmd;     
    $$;

当我执行上述存储过程时,得到以下输出。在这里,{country} 的第一个实例将替换为 CH(其中 CH 是我在执行此存储过程时发送的参数值),但不是第二个。

DELETE FROM ODP_SUBNATIONAL_STAGING.IDP_SUBNATIONAL_SALES_CH 
        WHERE COUNTRY_CODE = '{country}';

我期待下面的输出。

DELETE FROM ODP_SUBNATIONAL_STAGING.IDP_SUBNATIONAL_SALES_CH 
            WHERE COUNTRY_CODE = 'CH';

我还尝试了 Javascript 的 replaceAll 而不是 replace,但它返回了 [NULL]

请注意,由于我必须在多行中对 sql 进行硬编码,因此在将 sql 字符串存储到变量中时,我需要使用 Grave 重音符号。否则我会使用 " 符号来存储 sql 并使用 + 符号使其动态化。

如果有人能帮助解决这个问题,我们将非常感激。

【问题讨论】:

    标签: javascript stored-procedures replace snowflake-cloud-data-platform java-stored-procedures


    【解决方案1】:

    更安全的方法是使用绑定 - 如果您的计划是在存储过程中执行查询:

    
    create or replace temp table prefix_delete_me as 
    select 1 x, 'me' as country;
    
    CREATE OR REPLACE PROCEDURE testbind(COUNTRY VARCHAR) 
    RETURNS string
    LANGUAGE JAVASCRIPT
    AS
    $$
    
    var stmt = snowflake.createStatement({
        sqlText: `
            select *
            from identifier(:2)
            where country=:1
            and country != concat('hello', :1, :1)
        `
       , binds:[COUNTRY, 'prefix_delete_'+COUNTRY]
    });
    
    // execute the statement to prove its correct
    stmt.execute(); 
    
    // just get the sql statement
    return stmt.getSqlText();
    $$;
        
    call testbind('me')
    

    【讨论】:

    • 这看起来是比我的答案更好的解决方案。顺便说一句,我有什么办法可以使用CountryTable_:1 而不是使用identifier(:2)?因为在真实场景中我的 sql 会非常大,而且我的 sql 里面会有各种各样的表名。
    • 我尝试了不同的表名编码方式,但这是目前最好的方法
    【解决方案2】:

    您可以使用 JavaScript 模板文字 ${myVariable};那么您不必对字符串中用作模板的每个变量进行替换。只要你用反引号终止你的字符串文字,这就会起作用。

    CREATE OR REPLACE PROCEDURE CountryDelete(COUNTRY VARCHAR) 
        RETURNS string
        LANGUAGE JAVASCRIPT
        AS
        $$
            var error_msg = 'Success';      
            try 
            {
                var sql_cmd = `DELETE FROM MYSCHEMA.CountryTable_${COUNTRY} 
                WHERE COUNTRY_CODE = '${COUNTRY}';`      
                return sql_cmd;   
            }
            catch(err) 
            {
                error_msg += "ERROR : " + err.message;
            }
            return sql_cmd;     
        $$;
    

    【讨论】:

    • 当我编译这个脚本(在 DBVewer 中)时,它要求绑定变量。在调用此存储过程时,我也无法覆盖国家/地区。这就是它的工作原理吗?
    【解决方案3】:

    最后,我找到了一个解决方案,使用 RegExp 对象的构造函数。

    var sql_cmd = sql_cmd_temp.replace(new RegExp('{country}', 'g'), COUNTRY);
    

    这是更新后的代码。

    CREATE OR REPLACE PROCEDURE MYSCHEMA.CountryDelete(COUNTRY VARCHAR) 
        RETURNS string
        LANGUAGE JAVASCRIPT
        AS
        $$
            var error_msg = 'Success';      
            try 
            {
                var sql_cmd_temp = `DELETE FROM MYSCHEMA.CountryTable_{country} 
                WHERE COUNTRY_CODE = '{country}';`  
                var sql_cmd = sql_cmd_temp.replace(new RegExp('{country}', 'g'), COUNTRY);       
                return sql_cmd;   
            }
            catch(err) 
            {
                error_msg += "ERROR : " + err.message;
            }
            return sql_cmd;     
        $$;
    

    结果如下。

    DELETE FROM ODP_SUBNATIONAL_STAGING.IDP_SUBNATIONAL_SALES_CH 
                WHERE COUNTRY_CODE = 'CH';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-04
      • 2012-11-14
      • 2014-03-14
      • 2015-04-09
      • 1970-01-01
      • 2011-09-29
      相关资源
      最近更新 更多