2016-02-05 40 views
0

我想在python中编写一个SQL语句,它将表名作为变量传递。但是,我得到以下错误:必须声明表变量“@ P1”。我怎样才能传递一个表名作为SQL中的变量 - Python 3.4

pypyodbc.Programming Error: ('42000', '[42000]' [Miscrosoft] [SQL SERVER NATIVE CLIENT 10.0] [SQL SERVER] Must declare the table variable "@P1" 

产生错误的代码是:

query = cursor.execute('''SELECT * FROM ?''', (table_variable,)) 

我还有其他的代码,我传递变量使用的正常工作(下面的代码按预期工作)的语法相同的SQL语句。

query = cursor.execute('''SELECT column_name FROM information_schema.columns WHERE table_name = ?''', (table_variable,)) 

当我使用变量传递表名称时,该错误似乎发生。

任何帮助解决这个错误将不胜感激。

+1

您不能使用参数作为表名称。要做到这一点,需要动态的sql。 –

+0

此限制仅限于表名或是否存在其他参数无法传递的实例(我还没有找到任何详细说明这些限制的文档)。 – DonnRK

+1

参数旨在用于谓词来表示值。这意味着你可以在连接中使用它们,其中的子句等等。它们不是用来动态替换对象名称的。如果你想使用参数作为对象名称替换,你必须使用动态sql。如果沿着这条道路走,你不会从鲍比餐桌上出门,要小心。 http://bobby-tables.com/ –

回答

2

随着来自OP的新评论,这已经发生了很大的变化。如果你所要做的只是从每个表中获取几行样本,你可以很容易地利用sys.tables目录视图。这将为您的数据库中的每个表创建一个select语句。如果您有多个模式,则可以扩展此模式以添加模式名称。

select 'select top 10 * from ' + QUOTENAME(t.name) 
from sys.tables t 
2

你想要做的事情是不可能的。你只能传递值到查询作为参数 - 所以

SELECT * FROM @Table 

被禁止,但

SELECT * FROM TableName WHERE [email protected] 

是完全合法的。

现在,至于为什么它被禁止。从逻辑的角度来看,数据库层不能缓存你想要做的事情的查询计划 - 参数将完全彻底地改变它发生的地方和返回的地方 - 并且不能提前保证它是什么可以或不可以做。这就像试图在运行时加载抽象源文件并执行它 - 混乱,不可预知,不可靠和潜在的安全漏洞。

从可靠性的观点来看,请不要做

SELECT * FROM Table 

无论是。它使得你的代码不易读,因为你看不到会在哪里返回,但也不太可靠,因为它可能在没有警告的情况下改变并且破坏你的应用程序。

我知道它起初看起来很漫长,但老实说 - 编写单个的SELECT语句指定了他们实际想要返回的字段是更好的方法。它也将使您的应用程序运行更快:-)

+1

OP想要做的事情并非不可能。您可以轻松利用动态sql来执行此操作。不过,我会建议这样做并不是一个好主意,我完全同意创建个人查询是首选方法。 –

+0

OP的问题假设SQL被解析为一个宏语言并且动态插入了变量值,这不是真的 - 因此我为什么说这在SQL中是不可能的。例如,可以使用SAS或PowerShell。在SQL中执行类似于OP的尝试代码的唯一方法是动态SQL,我同意,但那会是类似query = cursor.execute('''EXEC(''SELECT * FROM''+?+ '')''',(table_variable,))和我们开始的很长的路,以及等待发生的坏主意和SQL注入攻击。 – eftpotrm

+0

同意你对动态sql的担忧,但说明这不可能是不准确的。是的,我们距离OP的开始还有很长的路要走,但那是因为他们开始的方式不起作用。 –

1

您可以定义一个字符串变量:

table_var_str = 'Table_name' 
st = 'SELECT * FROM ' + table_var_str 
query = cursor.execute(st) 

它会解决这个问题。

您还可以设置table_var_str作为一个列表:

table_var_str = [] 
st = [] 
for i in range(N): 
    table_var_str.append = 'Table_name' + str(i) 
    st.append('SELECT * FROM ' + table_var_str[i]) 
for j in range(J): 
    query = cursor.execute(st[j]) 

如果查询是很长,你应该把它们写在一条线上,而不是多线。

相关问题