Tom*_*ter 8 sql-server t-sql sql-server-2008-r2
我有一个简单的测试表,如下所示:
CREATE TABLE MyTable (x INT);
Run Code Online (Sandbox Code Playgroud)
在事务中,我尝试添加一列,然后插入到新创建的列中:
BEGIN TRANSACTION;
PRINT 'Adding column, ''SupplementalDividends'', to MyTable table.';
ALTER TABLE MyTable
ADD SupplementalDividends DECIMAL(18,6);
PRINT 'Column added successfully....';
PRINT 'Ready to INSERT into MyTable ...';
INSERT INTO MyTable (x, SupplementalDividends)
VALUES (1, 3.2);
PRINT '**** CHANGES COMPLETE -- COMMITTING.';
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
当我运行上面的代码时,问题是一条错误消息:
Invalid column name 'SupplementalDividends'.
Run Code Online (Sandbox Code Playgroud)
为什么这会导致错误?如果我在交易之外的不同批次中添加该列,它将起作用。我的问题是我想在事务中添加列。为什么会出错?
spa*_*dba 10
这是一个有约束力的问题。代码在编译时绑定到表的元数据,而不是后期绑定。尝试使用 EXEC 和动态 SQL 来克服此限制:
BEGIN TRANSACTION;
PRINT 'Adding column, ''SupplementalDividends'', to MyTable table.';
ALTER TABLE MyTable
ADD SupplementalDividends DECIMAL(18,6);
PRINT 'Column added successfully....';
PRINT 'Ready to INSERT into MyTable ...';
EXEC('
INSERT INTO MyTable (x, SupplementalDividends)
VALUES (1, 3.2);
')
PRINT '**** CHANGES COMPLETE -- COMMITTING.';
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用存储过程插入数据:后期绑定适用于存储过程,但不适用于即席查询。同样,您必须使用动态 SQL 来创建过程,但它可以让您更轻松地传递参数:
BEGIN TRANSACTION;
PRINT 'Adding column, ''SupplementalDividends'', to MyTable table.';
ALTER TABLE MyTable
ADD SupplementalDividends DECIMAL(18,6);
PRINT 'Column added successfully....';
PRINT 'Ready to INSERT into MyTable ...';
EXEC('
CREATE PROCEDURE insData @p1 int, @p2 DECIMAL(18,6)
AS
BEGIN
INSERT INTO MyTable (x, SupplementalDividends)
VALUES (@p1, @p2);
END')
EXEC InsData 1, 3.2;
PRINT '**** CHANGES COMPLETE -- COMMITTING.';
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
临时存储过程也可以:
BEGIN TRANSACTION;
PRINT 'Adding column, ''SupplementalDividends'', to MyTable table.';
ALTER TABLE MyTable
ADD SupplementalDividends DECIMAL(18,6);
PRINT 'Column added successfully....';
PRINT 'Ready to INSERT into MyTable ...';
EXEC('
CREATE PROCEDURE #insData @p1 int, @p2 DECIMAL(18,6)
AS
BEGIN
INSERT INTO MyTable (x, SupplementalDividends)
VALUES (@p1, @p2);
END')
EXEC #InsData 1, 3.2;
PRINT '**** CHANGES COMPLETE -- COMMITTING.';
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
只是想澄清一下,这是运行时的问题,而不是编译时的问题,与它们在同一个事务中的事实无关。例如,假设我们有这张表:
CREATE TABLE dbo.floob(a int);
Run Code Online (Sandbox Code Playgroud)
以下批处理成功解析(编译时),但在运行时它会收到您在问题中提到的错误:
BEGIN TRANSACTION;
ALTER TABLE dbo.floob ADD b int;
SELECT b FROM dbo.floob;
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
在 Management Studio 的查询编辑器中,您可以通过以下方式轻松解决此问题:
在它们之间放置一个批处理分隔符,如下所示:
BEGIN TRANSACTION;
ALTER TABLE dbo.floob ADD c int;
GO
SELECT c FROM dbo.floob;
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)如果您从 SQL Server 外部运行它(例如,从您的应用程序代码发送一个 SQL 批处理),您可以简单地以类似的方式分别发送两个批处理,或者如果您绝对需要将其作为一个批处理发送,您可以使用动态 SQL(如Gianluca 的回答)来推迟名称解析。
归档时间: |
|
查看次数: |
3663 次 |
最近记录: |