T-SQL检查和更新

时间:2017-06-23 15:10:44

标签: tsql

获取错误:

Msg 512, Level 16, State 1, Line 48
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Msg 512, Level 16, State 1, Line 87
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

如果没有记录= 0,00,需要检查表中的每条记录并更新表。然后使用当前值更新现有表。我希望能够跟踪当前数据并与旧数据进行比较。

DECLARE @LocTime DATETIME;
DECLARE @MinDateTime DATETIME;
DECLARE @SystemDateTime DATETIME;
DECLARE @LIR MONEY;
DECLARE @LOAR MONEY;
SELECT @SystemDateTime = SYSDATETIME(); --= '2016-12-07 23:30:00'
SELECT @MinDateTime = DATEADD(mi,-30,@SystemDateTime)   --go back half hour of reads, job is running every 10 minutes for overlap

--select  @MinDateTime, @SystemDateTime

IF OBJECT_ID(N'tempdb..##LastOver2') IS NOT NULL
BEGIN
    DROP TABLE ##LastOver2
END

--make temp table to hold found data
CREATE TABLE ##LastOver2 (ReadDate DATETIME
, FacilityName NVARCHAR(100)
, FacilityID UNIQUEIDENTIFIER
, LastInstantRead MONEY
, LastOverAllRead MONEY
, FacilityTimeZone INT
, FacilityTime DATETIME)

INSERT INTO ##LastOver2 (ReadDate, FacilityName
, FacilityID, LastInstantRead
, LastOverAllRead
, FacilityTimeZone, FacilityTime)
SELECT DISTINCT --why distinct?
fmr.ReadDate, f.Name
, f.FacilityID, fm.LastInstantRead
, fm.LastOverAllRead
, f.Timezone
, @LocTime
FROM [dbo].[Facilities] f WITH (NOLOCK)
JOIN [dbo].[FacilityMeters] fm WITH (NOLOCK)
ON F.FacilityID = FM.FacilityID 
JOIN FacilityMeterReadings fmr WITH (NOLOCK)
ON FM.FacilityMeterID = FMR.FacilityMeterID
WHERE  --fm.FacilityMeterID = '9268d1af-cc29-432c-9cdb-06c158180d2f'
(fmr.ReadDate >= @MinDateTime and ReadDate <= @SystemDateTime) --including on both side to continue with overlap
and (fm.IsVirtual = 0 and fm.ParentMeterID is NULL)
--and (fm.LastInstantRead = 0.00 and fm.LastOverAllRead = 0.00)
AND f.SuppressMonitoring = 0
select * from ##LastOver2

IF (select LastInstantRead from ##LastOver2) = 0.00 OR (SELECT LastOverAllRead FROM ##LastOver2) = 0.00
    BEGIN
            --UPDATE dbo.Facilities
            --SET SuppressMonitoring = 1
            --  FROM dbo.Facilities F 
            --  JOIN ##LastOver L
            --  ON F.FacilityID = l.FacilityID
            --  WHERE F.FacilityID = l.FacilityID

            DECLARE @body_content NVARCHAR(150);
            DECLARE @StartHour NVARCHAR(8) = '08:30:00' ;
            DECLARE @StopHour NVARCHAR(8) = '16:00:00';
            --why distinct, is it already distinct. Is is supposed to distinct the facility or meter?
            DECLARE @SQLScript NVARCHAR(200) = 'SELECT distinct * FROM ##LastOver2 WHERE CONVERT(TIME, FacilityTime) BETWEEN ' 
                        + CHAR(39) + @StartHour + CHAR(39)  +' AND ' + CHAR(39) + @StopHour + CHAR(39); 
                        --only looking for reads during day hours? shouldn't use between.

            DECLARE @copyRecipients NVARCHAR(100)


            SET @body_content = 'Please check the attached file. This was from server: ' + @@SERVERNAME

            DECLARE @fileName nvarchar(255);
            select @fileName = 'BadReading_' + replace(replace(convert(nvarchar(19),getdate(), 126),':',''),'-','') + '.txt';
            EXEC msdb.dbo.sp_send_dbmail
            @profile_name = 'SQLSupport'
            ,@recipients = 'Btest@test.com'
            --, @recipients = 'jira@cleanenergycollective.atlassian.net'
            --, @copy_recipients= @copyRecipients
            --, @copy_recipients= 'Bill.Lugaila@easycleanenergy.com;yvonne.lewis@easycleanenergy.com;don.munroe@easycleanenergy.com;Justin.Reed@easycleanenergy.com'
            , @query = @SQLScript
            , @subject = 'Facility Meter Check and Updating table'  --change so easier to see in emails
            , @body= @body_content
            , @importance= 'High'
            , @attach_query_result_as_file = 1
            , @query_attachment_filename = @fileName ;

            --select @SQLScript
    END
ELSE IF (select LastInstantRead from ##LastOver2) != 0.00 OR (SELECT LastOverAllRead FROM ##LastOver2) != 0.00
    BEGIN
        UPDATE [dbo].[_LastInstant_OverAll_Read]
        SET     [FacilityName] = lo.FacilityName,
                [LastInstantRead] = lo.LastInstantRead,
                [LastOverAllRead]= lo.LastOverAllRead,
                [Time_Date] = (SELECT CONVERT(DateTime, SysDateTime()))
        FROM ##LastOver2 lo
        WHERE  lo.FacilityName = [dbo].[_LastInstant_OverAll_Read].FacilityName
        AND lo.LastInstantRead != [dbo].[_LastInstant_OverAll_Read].LastInstantRead
        AND lo.LastOverAllRead != [dbo].[_LastInstant_OverAll_Read].LastOverAllRead
    END

1 个答案:

答案 0 :(得分:0)

以下内容可能会返回多行:

.
.
.
IF
(
    SELECT LastInstantRead
    FROM ##LastOver2
) = 0.00
OR
(
    SELECT LastOverAllRead
    FROM ##LastOver2
) = 0.00

.
.
.

IF
(
    SELECT LastInstantRead
    FROM ##LastOver2
) != 0.00
OR
(
    SELECT LastOverAllRead
    FROM ##LastOver2
) != 0.00

如果您希望它们只返回1行,那么您需要使用以下查询解决问题:

SELECT DISTINCT --why distinct?
              fmr.ReadDate,
              f.Name,
              f.FacilityID,
              fm.LastInstantRead,
              fm.LastOverAllRead,
              f.Timezone,
              @LocTime
       FROM [dbo].[Facilities] f WITH (NOLOCK)
            JOIN [dbo].[FacilityMeters] fm WITH (NOLOCK) ON F.FacilityID = FM.FacilityID
            JOIN FacilityMeterReadings fmr WITH (NOLOCK) ON FM.FacilityMeterID = FMR.FacilityMeterID
       WHERE  --fm.FacilityMeterID = '9268d1af-cc29-432c-9cdb-06c158180d2f'
       (fmr.ReadDate >= @MinDateTime
        AND ReadDate <= @SystemDateTime) --including on both side to continue with overlap
       AND (fm.IsVirtual = 0
            AND fm.ParentMeterID IS NULL)
       --and (fm.LastInstantRead = 0.00 and fm.LastOverAllRead = 0.00)
       AND f.SuppressMonitoring = 0;