在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?

Posted

技术标签:

【中文标题】在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?【英文标题】:Alternative to using dryRun to differentiate a Standard and Legacy SQL query in BigQuery? 【发布时间】:2019-03-05 12:04:20 【问题描述】:

什么

有谁知道使用 BigQuery API 识别/区分以旧版或标准 SQL 编写的视图或查询的更好方法?

想到的唯一方法是运行 SQL 并将 dryRun 属性设置为 true(这将产生最小的处理开销)并且如果它失败并显示包含短语“尝试使用标准SQL”我可以假设它是旧版 SQL,否则它可以工作并且是标准的。例如


...
"code": 400,
"message": 
    "Invalid table name: `my-project.my_dataset.hello_world`
    [Try using standard SQL (https://cloud.google.com/bigquery/docs/reference/standard-sql/enabling-standard-sql)]."

原因

我正在维护一个使用 BigQuery API 迁移数据的集成层(用 Cloud Functions - Node.js 8 编写)。

不幸的是,用户社区已被允许在标准或旧版 SQL 中编写视图和查询。由于在处理 Legacy SQL 时存在诸多限制,我想检测哪些查询和视图是使用它编写的,从而允许我相应地调整处理方法。

【问题讨论】:

【参考方案1】:

有谁知道使用 BigQuery API 识别/区分以旧版或标准 SQL 编写的视图或查询的更好方法?

您可以尝试使用 javascript 正则表达式来识别 SQL 的类型。

您可以使用以下代码 sn-p 作为基线

isStandardSql(idString) 
  let isStandard, fullId, partialId, projectId = '';
  // This 'if' checks if the provided idString is of type standard and makes sure there is only one ':' in the expression (as in legacy syntax)
  const splitted = idString.split(/[:.]/g);
  if (splitted.length > 3) 
    const __ret = this.try2findProjectId(idString, projectId);
    idString = __ret.idString;
    projectId = __ret.projectId;
  
  if ((idString.match(/:/g))) 
    // Regex that checks if the format of the id match legacy
    let matched = idString.match(/([\[]([^[]|[\[][\]])*[\]])/g);
    if (matched && matched[0]) 
    fullId = projectId + matched[0].substring(1, idString.length - 1);
    isStandard = false;
     else 
    this.errorMessage("First Regex", idString);
    
    // Same as the first only that here instead of ':' we are looking for '.' and we want to make sure there is more than 1 (as in standard syntax)
   else if ((idString.match(/\./g) && idString.match(/\./g).length === 2)) 
    // Regex that checks if the format of the id match standard
    let matched = idString.match(/(`([^`]|``)*`)/g);// ? idString.match(/(`([^`]|``)*`)/g) : [idString];
    if (matched && matched[0]) 
    fullId = projectId + matched[0].substring(1, idString.length - 1);
    isStandard = true
     else if(!matched && idString)
    fullId = projectId + idString;
    isStandard = true;
    
    else 
    this.errorMessage("Second Regex", idString);
    
  
  else //projectID.dataset
    // In case of id without projectId of proxy "use" project.dataset
    if(splitted.length === 2) 
      fullId = '';
      if (idString[0] === '[' && idString[idString.length - 1] === ']') 
        isStandard = false;
      
      else if (idString[0] === '`' && idString[idString.length - 1] === '`') 
        isStandard = true;
      
      partialId = idString.replace(/`|\[|\]/g, '')
    
    else 
      this.errorMessage("Third Regex", idString);
    
  
  // Return values is flag the determine the type (standard or legacy) and id without staring/ ending chars (``, [])
  return 
    isStandard,
    fullId: fullId,
    partialId: partialId
  ;
  


try2findProjectId(idString, projectId)
    
        let numOfInstances = 0
        for (let i = idString.length; i > 0; i--) 
            const char = idString[i - 1]
            if (char === ':' || char === '.') 
                numOfInstances++
                if (numOfInstances === 2) 
                    projectId = idString.substring(1, i - 1)
                    idString = idString.substring(i - 1, idString.length)
                    idString = idString[idString.length - 1] === '`' ? '`' + idString : idString
                    idString = idString[idString.length - 1] === ']' ? '[' + idString : idString
                
            
        
        return idString, projectId
    

【讨论】:

不错!您知道正则表达式的任何警告吗? IE。可能不适合的偷偷摸摸或奇怪的 SQL 示例?只是为了获得风险的大致百分比?或者你会考虑这个完整的覆盖范围吗? 到目前为止对我来说非常好用了几个月,没有任何问题。如果此答案有帮助,请将其标记为其他人关注的解决方案 我已将其标记为答案,但我不得不重新配置一些东西,并且第一个 if 语句“if (splitted.length > 3)”也遇到了问题,因为 if 引用缺少函数“try2findProjectId”。 @FreeZey 谢谢,我添加了缺少的功能,如果代码中还有其他需要改进的地方,请告诉我

以上是关于在 BigQuery 中使用 dryRun 区分标准和旧版 SQL 查询的替代方法?的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 试运行会返回啥?

错误标量子查询在 bigquery 中查询 json 文件

我可以以编程方式检查 google bigquery 查询成本吗?

Bigquery UDF 重复查询。错误:标量子查询不能超过一列

BigQuery 错误 - 标量子查询产生了多个元素

提高 BigQuery 不区分大小写的搜索性能