因为标题说当QUOTED_IDENTIFIER设置为OFF时DML查询失败,同时使用SqlDependancy监视表。 我在INSERT / UPDATE / DELETE语句中遇到以下错误:
以下是复制问题的代码,它是我能够创建的最小代码。
我使用了SQL 2008 R2和Visual Studio 2013(C#使用.Net Framework v4.5.1)
首先创建一个测试数据库,表并填充它。
USE [master]
GO
CREATE DATABASE [BUG0001]
GO
ALTER DATABASE [BUG0001] SET ENABLE_BROKER
GO
USE [BUG0001]
GO
CREATE TABLE [dbo].[Test]
(
[RowVersion]
ROWVERSION,
[TestId]
INT
NOT NULL,
[Flipper]
BIT
NOT NULL,
CONSTRAINT [PK_dbo_Test_TestId] PRIMARY KEY ([TestId])
)
GO
INSERT INTO [dbo].[Test] ([TestId], [Flipper])
VALUES (1, 0);
现在创建一个控制台应用程序并运行它(记得为数据库设置连接字符串)
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BUG0001
{
class Program
{
const string CN_STRING = "Server=TESTSERVER;Database=BUG0001;Trusted_Connection=True;";
const string SQL_DATA = "SELECT [RowVersion], [TestId], [Flipper] FROM [dbo].[Test] WHERE [RowVersion] > @LastRowVersion ORDER BY [RowVersion];";
const int FIELD_ROW_VERSION = 0;
const int FIELD_TEST_ID = 1;
const int FIELD_FLIPPER = 2;
static SqlConnection cn = null;
static byte[] lastRowVersion = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
static void Main(string[] args)
{
SqlDependency.Start(CN_STRING);
using (cn = new SqlConnection(CN_STRING))
{
cn.Open();
Console.WriteLine("Press any key to exit.");
Console.WriteLine();
GetData();
ConsoleKeyInfo keyInfo;
do { keyInfo = Console.ReadKey(true); }
while (keyInfo.Key == ConsoleKey.LeftWindows || keyInfo.Key == ConsoleKey.RightWindows);
cn.Close();
}
SqlDependency.Stop(CN_STRING);
}
static void GetData()
{
using (var cmd = cn.CreateCommand())
{
cmd.CommandText = SQL_DATA;
cmd.Parameters.Add(new SqlParameter("@LastRowVersion", lastRowVersion));
/* The SqlDependency is a one event only mechignisum and must be reset each time the event is triggered. */
var depenency = new SqlDependency(cmd);
depenency.OnChange += depenency_OnChange;
RenderResults(cmd);
}
}
static void depenency_OnChange(object sender, SqlNotificationEventArgs e)
{
Console.WriteLine(e.Info);
Console.WriteLine(e.Source);
Console.WriteLine(e.Type);
Console.WriteLine();
GetData();
}
static void RenderResults(SqlCommand cmd)
{
try
{
using (var reader = cmd.ExecuteReader())
{
foreach (DbDataRecord record in reader)
{
var rowVersion = (byte[])record.GetValue(FIELD_ROW_VERSION);
Console.WriteLine(
"[RowVersion] = 0x{0}\r\n[TestId] = '{1}'\r\n[Flipper] = '{2}'\r\n",
BitConverter.ToString(rowVersion).Replace("-", string.Empty),
record.GetInt32(FIELD_TEST_ID),
record.GetBoolean(FIELD_FLIPPER)
);
lastRowVersion = rowVersion;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
现在使用SQL Management Studio运行以下命令以获取错误
--SET QUOTED_IDENTIFIER ON /* Without Error */
SET QUOTED_IDENTIFIER OFF /* With Error */
GO
INSERT INTO [dbo].[Test] ([TestId], [Flipper]) VALUES (2, 0);
GO
UPDATE [dbo].[Test] SET [Flipper] = ~[Flipper] WHERE [TestId] = 1
GO
SELECT * FROM [dbo].[Test]
GO
DELETE FROM [dbo].[Test] WHERE [TestId] = 2
GO
SELECT * FROM [dbo].[Test]
GO
就像你对医生说“当我触摸它时疼痛”并且医生回应“好不要触摸它”我知道我可以在我的应用程序中使用“SET QUOTED_IDENTIFIER ON”但我正在监控由另一个应用程序创建和维护的表,无法控制它们如何设置QUOTED_IDENTIFIER。
有没有办法监控表而不会导致上面显示的问题?
也有人可以解释为什么会这样吗?
我在这里也发现了一个类似的问题(SQL Server: INSERT/UPDATE/DELETE failed because the following SET options have incorrect settings: ‘QUOTED_IDENTIFIER’),但没有提供如何处理这个问题的线索。