【发布时间】:2015-02-12 02:05:35
【问题描述】:
环境:Windows 64 位,python 2.7.8(32 位),pyodbc v. 3.0.7
对于我需要做的事情,根据内部政策,我不能使用链接服务器。
使用python,我正在尝试:
- 导出表的数据 (*.dat) 及其结构(格式 - *.fmt) 从一个使用 bcp 的 Sql Server(2008 或 2012)。出口的 文件位于我的本地计算机上。我打了 2 个 BCP 电话:一个是为了得到 格式(.fmt)文件,另一个获取数据(.dat)(无法 找到一种方法,一步完成)
- 将给定表的数据导入数据库 - 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