我有一个声明,我用来添加或更新一行数据。我在观察SQL更新行时没有明显的变化。我试图弄清楚SQL为什么要阻止它更新的原因。为什么SQL在没有检测到更改时更新某些行?
我以这种方式更新约1,000行(一个接一个),只有2行似乎更新时,我创建的掩码建议他们不应该。
下面是相关的SQL代码片段:
...
ELSE IF NOT EXISTS (
SELECT PERMIT_STATUS, PERMIT_LOCATION, PERMIT_COMMODITY, PERMIT_TYPE_CODE, PERMIT_TYPE_DESCRIPTION, PERMIT_ALLOCATION_METHOD, PERMIT_OPERATION_NAME, OWNERS, SHARE_PERCENTAGE, OPERATOR, MINERALS, PERMIT_DURATION_YEARS, PERMIT_DURATION_MONTHS, PERMIT_AREA, PERMIT_AREA_UNIT, PERMIT_OFFSHORE_ONSHORE, PERMIT_STATUS_DATE, PERMIT_MINERAL_GROUP, PERMIT_MP, SUBSEQUENT_TO_PERMIT, PERMIT_COMMENCEMENT_DATE, PERMIT_EXPIRY_DATE, PERMIT_GRANT_DATE, PERMIT_NONEXCLUSIVE_YN, ShapeGeoJson, Removed
FROM MyTable
WHERE PERMIT_NUMBER = @PERMIT_NUMBER
INTERSECT
SELECT @PERMIT_STATUS, @PERMIT_LOCATION, @PERMIT_COMMODITY, @PERMIT_TYPE_CODE, @PERMIT_TYPE_DESCRIPTION, @PERMIT_ALLOCATION_METHOD, @PERMIT_OPERATION_NAME, @OWNERS, @SHARE_PERCENTAGE, @OPERATOR, @MINERALS, @PERMIT_DURATION_YEARS, @PERMIT_DURATION_MONTHS, @PERMIT_AREA, @PERMIT_AREA_UNIT, @PERMIT_OFFSHORE_ONSHORE, @PERMIT_STATUS_DATE, @PERMIT_MINERAL_GROUP, @PERMIT_MP, @SUBSEQUENT_TO_PERMIT, @PERMIT_COMMENCEMENT_DATE, @PERMIT_EXPIRY_DATE, @PERMIT_GRANT_DATE, @PERMIT_NONEXCLUSIVE_YN, @ShapeGeoJson, @Removed
)
BEGIN
UPDATE MyTable
SET PERMIT_STATUS = @PERMIT_STATUS
,PERMIT_LOCATION = @PERMIT_LOCATION
,PERMIT_COMMODITY = @PERMIT_COMMODITY
,PERMIT_TYPE_CODE = @PERMIT_TYPE_CODE
,PERMIT_TYPE_DESCRIPTION = @PERMIT_TYPE_DESCRIPTION
,PERMIT_ALLOCATION_METHOD = @PERMIT_ALLOCATION_METHOD
,PERMIT_OPERATION_NAME = @PERMIT_OPERATION_NAME
,OWNERS = @OWNERS
,SHARE_PERCENTAGE = @SHARE_PERCENTAGE
,OPERATOR = @OPERATOR
,MINERALS = @MINERALS
,PERMIT_DURATION_YEARS = @PERMIT_DURATION_YEARS
,PERMIT_DURATION_MONTHS = @PERMIT_DURATION_MONTHS
,PERMIT_AREA = @PERMIT_AREA
,PERMIT_AREA_UNIT = @PERMIT_AREA_UNIT
,PERMIT_OFFSHORE_ONSHORE = @PERMIT_OFFSHORE_ONSHORE
,PERMIT_STATUS_DATE = @PERMIT_STATUS_DATE
,PERMIT_MINERAL_GROUP = @PERMIT_MINERAL_GROUP
,PERMIT_MP = @PERMIT_MP
,SUBSEQUENT_TO_PERMIT = @SUBSEQUENT_TO_PERMIT
,PERMIT_COMMENCEMENT_DATE = @PERMIT_COMMENCEMENT_DATE
,PERMIT_EXPIRY_DATE = @PERMIT_EXPIRY_DATE
,PERMIT_GRANT_DATE = @PERMIT_GRANT_DATE
,PERMIT_NONEXCLUSIVE_YN = @PERMIT_NONEXCLUSIVE_YN
,ShapeGeoJson = @ShapeGeoJson
,UpdatedUtc = GETUTCDATE()
,Removed = @Removed
,UpdatedMask = (
IIF (PERMIT_STATUS != @PERMIT_STATUS, 4096, 0) +
IIF (PERMIT_LOCATION != @PERMIT_LOCATION, 256, 0) +
IIF (PERMIT_COMMODITY != @PERMIT_COMMODITY, 512, 0) +
IIF (PERMIT_TYPE_CODE != @PERMIT_TYPE_CODE, 64, 0) +
IIF (PERMIT_TYPE_DESCRIPTION != @PERMIT_TYPE_DESCRIPTION, 128, 0) +
IIF (PERMIT_ALLOCATION_METHOD != @PERMIT_ALLOCATION_METHOD, 1024, 0) +
IIF (PERMIT_OPERATION_NAME != @PERMIT_OPERATION_NAME, 2048, 0) +
IIF (OWNERS != @OWNERS, 1048576, 0) +
IIF (SHARE_PERCENTAGE != @SHARE_PERCENTAGE, 2097152, 0) +
IIF (OPERATOR != @OPERATOR, 4194304, 0) +
IIF (MINERALS != @MINERALS, 8388608, 0) +
IIF (PERMIT_DURATION_YEARS != @PERMIT_DURATION_YEARS, 32768, 0) +
IIF (PERMIT_DURATION_MONTHS != @PERMIT_DURATION_MONTHS, 65536, 0) +
IIF (PERMIT_AREA != @PERMIT_AREA, 67108864, 0) +
IIF (PERMIT_AREA_UNIT != @PERMIT_AREA_UNIT, 134217728, 0) +
IIF (PERMIT_OFFSHORE_ONSHORE != @PERMIT_OFFSHORE_ONSHORE, 262144, 0) +
IIF (PERMIT_STATUS_DATE != @PERMIT_STATUS_DATE, 8192, 0) +
IIF (PERMIT_MINERAL_GROUP != @PERMIT_MINERAL_GROUP, 131072, 0) +
IIF (PERMIT_MP != @PERMIT_MP, 524288, 0) +
IIF (SUBSEQUENT_TO_PERMIT != @SUBSEQUENT_TO_PERMIT, 33554432, 0) +
IIF (PERMIT_COMMENCEMENT_DATE != @PERMIT_COMMENCEMENT_DATE, 16, 0) +
IIF (PERMIT_EXPIRY_DATE != @PERMIT_EXPIRY_DATE, 32, 0) +
IIF (PERMIT_GRANT_DATE != @PERMIT_GRANT_DATE, 8, 0) +
IIF (PERMIT_NONEXCLUSIVE_YN != @PERMIT_NONEXCLUSIVE_YN, 16384, 0) +
IIF (ShapeGeoJson != @ShapeGeoJson, 137438953472, 0) +
IIF (Removed != @Removed, 274877906944, 0)
)
WHERE PERMIT_NUMBER = @PERMIT_NUMBER;
END
...
我使用顶部的INTERSECT
方法来检测任何行的数据列的变化。这是因为比较列中的NULL值更容易。
而且您可以看到UpdatedMask正在更新一个值,以指示哪些列已更新。发生问题时,将其设置为0(并且按预期工作时,我会看到正确的UpdatedMask)。
我看不到任何拼写错误或明显的逻辑错误。所以我想知道是否可能是由于SQL Azure负载不知何故,通过大量的ShapeGeoJson列逐个更新这么多的记录?
这里的表定义的情况下,它是非常有用的:
CREATE TABLE [dbo].[MyTable](
[PERMIT_NUMBER] [varchar](30) NOT NULL,
[PERMIT_STATUS] [varchar](30) NULL,
[PERMIT_LOCATION] [varchar](4000) NULL,
[PERMIT_COMMODITY] [varchar](8) NULL,
[PERMIT_TYPE_CODE] [varchar](4000) NULL,
[PERMIT_TYPE_DESCRIPTION] [varchar](255) NULL,
[PERMIT_ALLOCATION_METHOD] [varchar](4000) NULL,
[PERMIT_OPERATION_NAME] [varchar](4000) NULL,
[OWNERS] [varchar](4000) NULL,
[SHARE_PERCENTAGE] [varchar](4000) NULL,
[OPERATOR] [varchar](220) NULL,
[MINERALS] [varchar](4000) NULL,
[PERMIT_DURATION_YEARS] [varchar](4000) NULL,
[PERMIT_DURATION_MONTHS] [varchar](4000) NULL,
[PERMIT_AREA] [varchar](4000) NULL,
[PERMIT_AREA_UNIT] [varchar](4) NULL,
[PERMIT_OFFSHORE_ONSHORE] [varchar](4000) NULL,
[PERMIT_STATUS_DATE] [date] NULL,
[PERMIT_MINERAL_GROUP] [varchar](4000) NULL,
[PERMIT_MP] [varchar](4000) NULL,
[SUBSEQUENT_TO_PERMIT] [varchar](4000) NULL,
[PERMIT_COMMENCEMENT_DATE] [date] NULL,
[PERMIT_EXPIRY_DATE] [date] NULL,
[PERMIT_GRANT_DATE] [date] NULL,
[PERMIT_NONEXCLUSIVE_YN] [char](1) NULL,
[ShapeGeoJson] [varchar](max) NOT NULL,
[CreatedUtc] [datetime] NOT NULL,
[UpdatedUtc] [datetime] NOT NULL,
[Removed] [bit] NOT NULL,
[UpdatedMask] [bigint] NULL,
CONSTRAINT [PK_MyTable_1] PRIMARY KEY CLUSTERED
(
[PERMIT_NUMBER] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
任何想法?
更新过程每晚都会运行,因此我会密切关注那些似乎违反规则的行,以查看是否存在某种模式。我现在已经看过几次了,但忽略了保留之前调查的数据。
看到这种类型的代码给我的噩梦。我会建议使用ORM。 –
@MarAnderson - 我正在使用Dapper,但是因为我不想每次往返取一个巨大的ShapeGeoJson时都返回数据库,所以只需比较一下我就可以保存SQL Azure DTU在添加/更新过程中单一电话。但是,是的,并不是最优雅的SQL。 – Gavin
请阅读[this](http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/)了解一些关于改善问题的提示。 – HABO