Ich habe einen Tisch wie diesen:

CREATE TABLE CarRentSchedule
(
    carId INTEGER NOT NULL,
    rent_start INTEGER NOT NULL,
    rent_end INTEGER NOT NULL,
    personId INTEGER NOT NULL,
    tariff INTEGER NOT NULL,
    PRIMARY KEY carId,
    FOREIGN KEY (personId) REFERENCES Persons(PersonID)
    CONSTRAINT CHK_CR_AVLBL CHECK (dbo.CarCheck(carId , rent_start , rent_end ) = 1))

Und ich muss jede Kreuzung der Mietzeit für dasselbe Auto verbieten. Ich habe festgestellt, dass sich der zurückgegebene Wert bei Verwendung einer Funktion (Beispiel unten) innerhalb der Einschränkung von dem Wert unterscheidet, der außerhalb der Einschränkung verwendet wird.

if exists (select * from dbo.CarRentSchedule rt
               where rt.carId = @id 
                 and ((rt.rent_Start >= @startTime and rt.rent_end < @endTime)
                      or  
                      (rt.rent_end <= @endTime and rt.rent_end > @startTime)
                      or 
                      (rt.rent_Start < @endTime and rt.rent_end > @startTime)
                      or 
                      (rt.rent_Start >= @startTime and rt.rent_end <= @endTime)))
        return 0

Wenn ich also versuche, Daten in die Tabelle einzufügen, würde mir die Einschränkung aus irgendeinem Grund dies niemals erlauben.

Ich habe überprüft, ob die Funktion beim Aufrufen von der Einschränkung NULL zurückgibt, jedoch die Funktion wie folgt aufruft

select dbo.CheckFunc(1, 10, 15, 1, 1) 

Würde 0/1 zurückgeben, wie es soll. Ich habe auch überprüft und herausgefunden, dass wenn die Funktion kein SELECT enthält (z. B. eine einfache Vergleichsoperation), sie auch in der Einschränkung einwandfrei funktioniert.

Könnte jemand erklären, warum das so funktioniert? Ist es eine Einschränkung, die die Verwendung von SELECTs innerhalb der Einschränkungen verbietet, oder liegt es daran, dass SELECT auf dieselbe Tabelle verweist, auf die die Einschränkung angewendet wurde?

2
daaibraanies 17 Feb. 2020 im 09:25

3 Antworten

Beste Antwort

Ich vermute, dass beim Überprüfen der zweiten Einschränkung der neue Eintrag bereits als Teil der Tabelle betrachtet wird, sodass er sich immer mit sich selbst überschneidet. Aber das scheint seltsam, nicht wahr?

Also, ja, es scheint so, ich habe die Funktion neu geschrieben, damit sie den neu hinzugefügten Eintrag nicht berücksichtigt und jetzt funktioniert. Seltsamerweise würde ich mir einfach nicht vorstellen, dass ein Eintrag, der gerade getestet wird, um hinzugefügt zu werden, an der Seitenauswahl aus dieser Tabelle teilnehmen würde.

0
daaibraanies 17 Feb. 2020 im 22:52

Können Sie unten versuchen, ob das funktioniert:

Alter function AvailableCar
    (@car integer, @startTime integer, @endTime integer)
returns integer 
as
begin
declare @value int
    set @value = (select max(1) from dbo.CarRentSchedule as rt
               where rt.roomId = @car 
                 and ((rt.rent_Start >= @startTime and p.occ_start < @endTime)
                      or  
                      (rt.rent_end <= @endTime and rt.rent_end > @startTime)
                      or 
                      (rt.rent_Start < @endTime and rt.rent_end > @startTime)
                      or 
                      (rt.rent_Start >= @startTime and rt.rent_end <= @endTime)))
       if (@value is NULL)
       set @value = 0

       return @value


end
0
daaibraanies 18 Feb. 2020 im 00:12

Dies beantwortet die Originalversion der Frage.

Ihre erste Bedingung sollte mit einer check Einschränkung behandelt werden:

check (occ_end > occ_start)

Dann könnte eine korrekte Logik für Überlappungen hilfreich sein. Ich würde vorschlagen:

if exists (select 1
           from dbo.RoomSchedule rs
           where p.roomId = @rn and
                 p.occ_end >= @startTime and 
                 p.occ_start < @endTime
          )

Zwei Zeiträume überschneiden sich, wenn der erste vor dem zweiten und der erste nach dem ersten beginnt.

0
Gordon Linoff 18 Feb. 2020 im 20:15