SQL服务器:存储过程中的更新发生了一件奇怪的事情
SQL Server : a strange thing happens with an Update inside a stored procedure
我在 SQL Server 2005 中有一个存储过程,里面的代码是这样的:
select Unique_ID as ID
into tmp_table
from table1
然后,在其他一些陈述之后,我进行了此更新:
Update table1
set Flag = ‘Y’
Where Unique_ID in (select Unique_ID from tmp_table)
如您所见,我在更新时故意将 ID
误认为 Unique_ID
(tmp_table
中的列名)。
现在发生了奇怪的事情,SQL服务器在我执行存储过程时没有显示错误。
它忽略错误所在的行:
Where Unique_ID in (select Unique_ID from tmp_table)
然后运行这个:
Update table1 set
Flag = ‘Y’
有什么想法吗?
非常感谢。
更新:
存储过程代码如下:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[MyProc]
AS
BEGIN
SET NOCOUNT ON
DECLARE @date VARCHAR(20)
SET @date = REPLACE(CONVERT(VARCHAR(8), GETUTCDATE(), 3), '/', '')
+ REPLACE(CONVERT(VARCHAR(8), GETUTCDATE(), 108), ':', '')
DECLARE @PATH AS VARCHAR(500)
SET @PATH = 'C:\MyPath\'
BEGIN TRY
EXEC master.dbo.xp_create_subdir @PATH
END TRY
BEGIN CATCH
PRINT 'FOLDER NOT CREATED'
END CATCH
IF EXISTS (SELECT name FROM sys.tables WHERE name = 'TMP_TABLE')
DROP TABLE TMP_TABLE
SELECT
UNIQUE_ID [Unique ID] ,
'col1' COL1,
'col2' COL2,
'col3' COL3,
'col4' COL4
INTO
TMP_TABLE
FROM
TABLE1
WHERE
Flag IN 'N'
--Try to generate file, If there was any problem, return from the SP => no update
BEGIN TRY
DECLARE @QUERY VARCHAR(MAX)
SET @QUERY = 'EXEC master..xp_cmdshell ''sqlcmd -E -s"," -W -h-1 -Q "SET NOCOUNT ON;SELECT * FROM dbo.TMP_TABLE" | findstr /V /C:"-" /B > '
+ @PaTH + '\FileName_' + @date + '.csv'',no_output;'
EXEC(@QUERY)
END TRY
BEGIN CATCH
PRINT 'Exception during file generation'
RETURN
END CATCH
PRINT 'File Generated'
UPDATE TABLE1
SET Flag = 'Y',
MODIFICATION_DATE = GETDATE()
WHERE
UNIQUE_ID IN (SELECT UNIQUE_ID FROM TMP_TABLE)
BEGIN TRY
DROP TABLE dbo.TMP_TABLE
PRINT 'TMP table dropped'
END TRY
BEGIN CATCH
PRINT 'TMP table not dropped'
END CATCH
END
GO
问题出在这一行:
WHERE UNIQUE_ID IN (SELECT **UNIQUE_ID** FROM TMP_TABLE)
我应该用 [UNIQUE ID]
替换 UNIQUE_ID
但是SQL服务器不会抛出错误,它只是更新所有记录。
这里是表 1 的结构:
CREATE TABLE [dbo].[TABLE1]
(
UNIQUE_ID int NOT NULL IDENTITY(1, 1), --Primary key
Flag [varchar] (1) ,
MODIFICATION_DATE datetime,
)
我假设您的查询有错字。你的桌子是这样的吗?
create table1
( Unique_ID int
, Flag char(1)
, ...
);
create tmp_table
( [Unique ID] int primary key
, ...
);
在这种情况下,您的查询是:
Update table1 t1 set
Flag = ‘Y’
Where t1.Unique_ID in (select t1.Unique_ID from tmp_table)
除了您的 id 为 null 外,这是正确的。您只需将 table1 中的 Unique_ID 与其自身进行比较。
尝试通过使用 table 名称来明确引用要比较的列:
UPDATE TABLE1
SET Flag = 'Y',
MODIFICATION_DATE = GETDATE()
WHERE
UNIQUE_ID IN (SELECT TMP_TABLE.UNIQUE_ID FROM TMP_TABLE)
混淆是因为在两个 table 上都有一个名为 UNIQUE_ID
的列,所以通过在子选择中使用 table 名称对其进行完全限定,您可以 100% 确定您指的是正确的列。
我在 SQL Server 2005 中有一个存储过程,里面的代码是这样的:
select Unique_ID as ID
into tmp_table
from table1
然后,在其他一些陈述之后,我进行了此更新:
Update table1
set Flag = ‘Y’
Where Unique_ID in (select Unique_ID from tmp_table)
如您所见,我在更新时故意将 ID
误认为 Unique_ID
(tmp_table
中的列名)。
现在发生了奇怪的事情,SQL服务器在我执行存储过程时没有显示错误。
它忽略错误所在的行:
Where Unique_ID in (select Unique_ID from tmp_table)
然后运行这个:
Update table1 set
Flag = ‘Y’
有什么想法吗?
非常感谢。
更新:
存储过程代码如下:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[MyProc]
AS
BEGIN
SET NOCOUNT ON
DECLARE @date VARCHAR(20)
SET @date = REPLACE(CONVERT(VARCHAR(8), GETUTCDATE(), 3), '/', '')
+ REPLACE(CONVERT(VARCHAR(8), GETUTCDATE(), 108), ':', '')
DECLARE @PATH AS VARCHAR(500)
SET @PATH = 'C:\MyPath\'
BEGIN TRY
EXEC master.dbo.xp_create_subdir @PATH
END TRY
BEGIN CATCH
PRINT 'FOLDER NOT CREATED'
END CATCH
IF EXISTS (SELECT name FROM sys.tables WHERE name = 'TMP_TABLE')
DROP TABLE TMP_TABLE
SELECT
UNIQUE_ID [Unique ID] ,
'col1' COL1,
'col2' COL2,
'col3' COL3,
'col4' COL4
INTO
TMP_TABLE
FROM
TABLE1
WHERE
Flag IN 'N'
--Try to generate file, If there was any problem, return from the SP => no update
BEGIN TRY
DECLARE @QUERY VARCHAR(MAX)
SET @QUERY = 'EXEC master..xp_cmdshell ''sqlcmd -E -s"," -W -h-1 -Q "SET NOCOUNT ON;SELECT * FROM dbo.TMP_TABLE" | findstr /V /C:"-" /B > '
+ @PaTH + '\FileName_' + @date + '.csv'',no_output;'
EXEC(@QUERY)
END TRY
BEGIN CATCH
PRINT 'Exception during file generation'
RETURN
END CATCH
PRINT 'File Generated'
UPDATE TABLE1
SET Flag = 'Y',
MODIFICATION_DATE = GETDATE()
WHERE
UNIQUE_ID IN (SELECT UNIQUE_ID FROM TMP_TABLE)
BEGIN TRY
DROP TABLE dbo.TMP_TABLE
PRINT 'TMP table dropped'
END TRY
BEGIN CATCH
PRINT 'TMP table not dropped'
END CATCH
END
GO
问题出在这一行:
WHERE UNIQUE_ID IN (SELECT **UNIQUE_ID** FROM TMP_TABLE)
我应该用 [UNIQUE ID]
UNIQUE_ID
但是SQL服务器不会抛出错误,它只是更新所有记录。
这里是表 1 的结构:
CREATE TABLE [dbo].[TABLE1]
(
UNIQUE_ID int NOT NULL IDENTITY(1, 1), --Primary key
Flag [varchar] (1) ,
MODIFICATION_DATE datetime,
)
我假设您的查询有错字。你的桌子是这样的吗?
create table1
( Unique_ID int
, Flag char(1)
, ...
);
create tmp_table
( [Unique ID] int primary key
, ...
);
在这种情况下,您的查询是:
Update table1 t1 set
Flag = ‘Y’
Where t1.Unique_ID in (select t1.Unique_ID from tmp_table)
除了您的 id 为 null 外,这是正确的。您只需将 table1 中的 Unique_ID 与其自身进行比较。
尝试通过使用 table 名称来明确引用要比较的列:
UPDATE TABLE1
SET Flag = 'Y',
MODIFICATION_DATE = GETDATE()
WHERE
UNIQUE_ID IN (SELECT TMP_TABLE.UNIQUE_ID FROM TMP_TABLE)
混淆是因为在两个 table 上都有一个名为 UNIQUE_ID
的列,所以通过在子选择中使用 table 名称对其进行完全限定,您可以 100% 确定您指的是正确的列。