【问题标题】:With pyodbc on SQL Server, create table using select * into table from openrowset(BULK ... ) has no effect在 SQL Server 上使用 pyodbc,使用 select * into table from openrowset(BULK ... ) 创建表无效
【发布时间】:2015-02-12 02:05:35
【问题描述】:

环境:Windows 64 位,python 2.7.8(32 位),pyodbc v. 3.0.7

对于我需要做的事情,根据内部政策,我不能使用链接服务器。

使用python,我正在尝试:

  1. 导出表的数据 (*.dat) 及其结构(格式 - *.fmt) 从一个使用 bcp 的 Sql Server(2008 或 2012)。出口的 文件位于我的本地计算机上。我打了 2 个 BCP 电话:一个是为了得到 格式(.fmt)文件,另一个获取数据(.dat)(无法 找到一种方法,一步完成)
  2. 将给定表的数据导入数据库 - MyDatabase - 我拥有完全权限(根据 DBA 的声明),并且可以在相同的 SQL 服务器但不同的数据库上,或者完全在另一台服务器上。在这里,我的主要目标是自动创建要导入的表(基于导出的 fmt 文件)以及实际导入其数据。

我已经完成了第 1 点,我可以在其中动态指定要导出的服务器、目录、模式和表,python 会自动在我的本地计算机上的专用文件夹下创建 table.dat 和 table.fmt 文件 -专用共享文件夹

DedicatedShareFolder 是我本地机器上的一个共享文件夹,用于存储导出的表及其 fmt 文件。我尝试将这些表导入其中的 SQL Server 可以访问它。

在第2点中,我使用python构建SQL语句如下:

sql = "select * into %s from
openrowset(BULK '\\\\%s\\sqltemp\\%s.dat', 
FORMATFILE = '\\\\%s\\sqltemp\%s.fmt') as A" %(newTableName,os.environ['COMPUTERNAME'],
table,os.environ['COMPUTERNAME'],table)

最终看起来像:

select A.* into MyDatabase.dbo.blah48 from
openrowset(BULK '\\MyMachineName\DedicatedShareFolder\table.dat', 
FORMATFILE = '\\MyMachineName\DedicatedShareFolder\table.fmt') as A;

我创建一个到具有 MyDatabase 的 SQL 服务器的连接,然后执行:

cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=%s;DATABASE=%s;UID=%s;PWD=%s' % (server, catalog, login, pw))
cursor = cnxn.cursor()
rows = cursor.execute(sql).rowcount
print "Done importing %s rows" %rows

我明白了:

Done importing 606597 rows

唉,表没有创建

我使用“ODBC 数据源管理”的“跟踪”选项卡在本地计算机上运行了跟踪。我打开日志文件,找不到与创建表有关的任何错误。我确实看到这样的条目:

test_DB 5200-5a28   EXIT  SQLDriverConnectW  with return code 1 (SQL_SUCCESS_WITH_INFO)
        HDBC                0x03C59190
        HWND                0x00000000
        WCHAR *             0x74C28B34 [      -3] "******\ 0"
        SWORD                       -3 
        WCHAR *             0x74C28B34 <Invalid buffer length!> [-3]
        SWORD                       -3 
        SWORD *             0x00000000
        UWORD                        0 <SQL_DRIVER_NOPROMPT>

        DIAG [01000] [Microsoft][ODBC SQL Server Driver][SQL Server]Changed database context to 'mydatabase'. (5701) 

        DIAG [01000] [Microsoft][ODBC SQL Server Driver][SQL Server]Changed language setting to us_english. (5703) 

        DIAG [01S00] [Microsoft][ODBC SQL Server Driver]Invalid connection string attribute (0) 

我怀疑“无效的缓冲区长度”在这里没有作用(在我的搜索中找不到有关它的信息),我确实看到驱动程序成功地更改了上下文和语言。

我还在跟踪日志中看到了一些这样的条目:

test_DB 50c0-4fec   EXIT  SQLGetTypeInfo  with return code -1 (SQL_ERROR)
        HSTMT               0x03AC8E80
        SWORD                       12 <SQL_VARCHAR>

        DIAG [24000] [Microsoft][ODBC Driver Manager] Invalid cursor state (0) 

在我的搜索中没有发现任何表明“无效光标状态”在这里有任何影响的重要信息。以上条目可能是由于我仍在处理代码的其他部分。

在跟踪日志的下方,我看到了:

test_DB 50c0-4fec   ENTER SQLExecDirect 
        HSTMT               0x03ACB5B0
        UCHAR *             0x025BBB94 [      -3] "select A.* into MyDatabase.dbo.blah48 from
openrowset(BULK '\\MyMachineName\DedicatedShareFolder\table.dat', 
FORMATFILE = '\\MyMachineName\DedicatedShareFolder\table.fmt') as A\ 0"
        SDWORD                    -3

test_DB 50c0-4fec   EXIT  SQLExecDirect  with return code 0 (SQL_SUCCESS)
        HSTMT               0x03ACB5B0
        UCHAR *             0x025BBB94 [      -3] "select A.* into MyDatabase.dbo.blah48 from
openrowset(BULK '\\MyMachineName\DedicatedShareFolder\table.dat', 
FORMATFILE = '\\MyMachineName\DedicatedShareFolder\table.fmt') as A\ 0"
        SDWORD                    -3

test_DB 50c0-4fec   ENTER SQLRowCount 
        HSTMT               0x03ACB5B0
        SQLLEN *            0x0027EFD4

test_DB 50c0-4fec   EXIT  SQLRowCount  with return code 0 (SQL_SUCCESS)
        HSTMT               0x03ACB5B0
        SQLLEN *            0x0027EFD4 (606597)

跟踪文件指示表已创建。可惜不是。

出于绝望,我查看了我正在测试的服务器上的每个数据库。任何地方都没有废话表,即使 MyDatabase 是我唯一拥有写权限的表

如果我在 Microsoft SQL Server Management Studio 中执行相同的“select * into ... openrowset ... bulk ...”语句,它会成功(以 python 脚本中使用的同一用户登录)

我在同一个脚本中使用函数成功地执行了许多其他与 SQL 相关的任务。导入是唯一不起作用的。

我还运行了所有我能想到的否定单元测试,以确保没有变量在中途被更改。什么都没有。

我是python的初学者。我要么在我的代码中做错了什么,要么?

如果不能使用“select * into .. openrowset etc”类型的语句来实现我的目标,我可以使用哪些其他 SLQ 解决方案来创建表并根据其 BCP dat 和 fmt 文件加载其数据?

谢谢。

【问题讨论】:

    标签: sql-server-2008 python-2.7 sql-server-2012 pyodbc openrowset


    【解决方案1】:

    默认情况下,Connection 对象中禁用了事务的自动提交。您请求的所有工作实际上都已完成,事务只是在连接关闭时回滚。

    几个选项:

    1. 使用Connection.commit()Cursor.commit() 提交您的更改。它们在功能上是相同的,添加了Cursor.commit(),因此不必跟上Connection 对象。

    2. 在创建连接时将autocommit 变量设置为True。请注意,它是pyodbc.connect() 函数的参数,它不是连接字符串的一部分。使用您的编码风格设置autocommit 将是:

      .... cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=%s;DATABASE=%s;UID=%s;PWD=%s' % (服务器, 目录, 登录, pw), 自动提交=真) ……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 2016-01-11
      相关资源
      最近更新 更多