AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 29925
Accepted
Rachel
Rachel
Asked: 2012-12-07 05:43:50 +0800 CST2012-12-07 05:43:50 +0800 CST 2012-12-07 05:43:50 +0800 CST

当 SQL 不会执行时,如何阻止 SQL 验证 OPENROWSET 查询?

  • 772

我有一个存储过程引发错误的问题,因为它试图在其中运行/验证OPENROWSET它实际上不必执行的查询。

看起来像这样的存储过程:

IF (@flagA = 1)
BEGIN
    INSERT INTO #tmpData(Column1, Column2, Column3)
    SELECT A, B, C
    FROM (
        SELECT *
        FROM OPENROWSET(
            'Microsoft.ACE.OLEDB.12.0', 
            'Text; HDR=Yes; Database=\\server\tmpFiles', 
            'SELECT * FROM FileA.txt')
    ) as T
END

IF (@flagB = 1)
BEGIN
    INSERT INTO #tmpData(Column1, Column2, Column3)
    SELECT D, E, F
    FROM (
        SELECT *
        FROM OPENROWSET('Microsoft.Ace.OLEDB.12.0', 
        'Excel 8.0;Database=\\server\tmpFiles\FileB.xls', 
        'SELECT * FROM [Sheet$]')
    ) as T
END

IF (@flagC = 1)
BEGIN
    INSERT INTO #tmpData(Column1, Column2, Column3)
    SELECT G, H, I
    FROM (
        SELECT *
        FROM OPENROWSET('Microsoft.Ace.OLEDB.12.0', 
        'Excel 8.0;Database=\\server\tmpFiles\FileC.xls', 
        'SELECT * FROM [Sheet1$]')
    ) as T
END

请注意,每个OPENROWSET文件都以不同的格式引用具有不同列名的不同文件。

我的问题是,如果其中一个文件不存在,或者以错误的格式存在(例如有人错误地将 FileB 上传为 FileC),即使该OPENROWSET查询永远不会在该过程尝试运行时出现错误意味着被执行。

例如,如果 FileB 不存在并且您尝试使用 运行该过程@flagB = 0,它将抛出一个错误,说它找不到链接服务器FileB

或者,如果用户错误地将 a 上传FileB为 a FileC,然后通过从表单中删除来纠正自己FileC,它会在下次运行过程时抛出错误Cannot process the object "SELECT * FROM [Sheet1$]",因为 FileC 不会有一个名为 的工作表Sheet1,即使@flagC = 0

OPENROWSET如果查询不是被执行的,我如何防止 SQL 验证查询?

sql-server sql-server-2005
  • 1 1 个回答
  • 1494 Views

1 个回答

  • Voted
  1. Best Answer
    Kevin Feasel
    2012-12-07T07:35:37+08:002012-12-07T07:35:37+08:00

    有几个选项可用。其中之一是为您的插入调用使用动态 SQL。这样,在执行发生之前,验证实际上不会发生。对于您的示例,它可能如下所示:

    declare @sql nvarchar(max);
    
    IF (@flagA = 1)
    BEGIN
    set @sql = N'
        INSERT INTO #tmpData(Column1, Column2, Column3)
        SELECT A, B, C
        FROM (
            SELECT *
            FROM OPENROWSET(
                ''Microsoft.ACE.OLEDB.12.0'', 
                ''Text; HDR=Yes; Database=\\server\tmpFiles'', 
                ''SELECT * FROM FileA.txt'')
        ) as T
    ';
    END
    
    IF (@flagB = 1)
    BEGIN
    set @sql = N'
        INSERT INTO #tmpData(Column1, Column2, Column3)
        SELECT D, E, F
        FROM (
            SELECT *
            FROM OPENROWSET(''Microsoft.Ace.OLEDB.12.0'', 
            ''Excel 8.0;Database=\\server\tmpFiles\FileB.xls'', 
            ''SELECT * FROM [Sheet$]'')
        ) as T
    ';
    END
    
    IF (@flagC = 1)
    BEGIN
    set @sql = N'
        INSERT INTO #tmpData(Column1, Column2, Column3)
        SELECT G, H, I
        FROM (
            SELECT *
            FROM OPENROWSET(''Microsoft.Ace.OLEDB.12.0'', 
            ''Excel 8.0;Database=\\server\tmpFiles\FileC.xls'', 
            ''SELECT * FROM [Sheet1$]'')
        ) as T
    ';
    END
    
    execute sp_executesql @sql;
    

    在这种情况下,验证直到运行时才会发生。缺点是故障排除变得更加困难,因为您现在正在尝试调试动态 SQL。

    您还可以将几个单独的语句合并为一个。

    第二种选择是将调用拆分为单独的过程。我会把它放在遥远的第二位,主要是因为它很容易滥用它并开始假装 T-SQL 存储过程等同于 C 风格的方法,而忘记了可能存在显着的性能差异。无论如何,将 INSERT 语句移动到三个单独的过程中并传入任何必要的参数,如下所示:

    IF (@flagA = 1)
    BEGIN
        exec InsertFlagA @parms1;
    END
    
    IF (@flagB = 1)
    BEGIN
        exec InsertFlagB @parms2;
    END
    
    IF (@flagC = 1)
    BEGIN
        exec InsertFlagB @parms3;
    END
    

    您无法使用临时表执行此操作,因此除非您有永久“临时”表可用(或使用全局临时表),否则可能会丢弃此选项。

    如果您确实想使用临时表,可以将 exec 语句更改为insert into #tmpData exec InsertFlagA @parms1.

    • 3

相关问题

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

  • 从 SQL Server 2008 降级到 2005

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve