sql >> Database teknologi >  >> RDS >> Sqlserver

Tabelværdi-funktion - Bestil efter ignoreres i output

Der var to ting galt med din oprindelige tilgang.

  1. Ved indsættelse i tabellen blev det aldrig garanteret, at ORDER BYINSERT ... SELECT ... ORDER BY ville være den rækkefølge, som rækkerne faktisk blev indsat.
  2. Når du vælger fra det, garanterer SQL Server ikke, at SELECT uden en ORDER BY returnerer rækkerne i en bestemt rækkefølge, såsom indsættelsesrækkefølge alligevel.

I 2012 ser det ud til, at adfærden har ændret sig i forhold til punkt 1. Den ignorerer nu generelt ORDER BYSELECT sætning, der er kilden til en INSERT

DECLARE @T TABLE(number int)

INSERT INTO @T 
SELECT number
FROM master..spt_values
ORDER BY name

2008-plan

2012-plan

Årsagen til ændringen af ​​adfærd er, at SQL Server i tidligere versioner producerede en plan, der blev delt mellem udførelser med SET ROWCOUNT 0 (fra) og SET ROWCOUNT N . Sorteringsoperatøren var kun der for at sikre den korrekte semantik i tilfælde af at planen blev kørt af en session med en ROWCOUNT ikke nul sæt. TOP operatør til venstre for den er en ROWCOUNT TOP .

SQL Server 2012 producerer nu separate planer for de to sager, så der er ingen grund til at tilføje disse til ROWCOUNT 0 version af planen.

En sortering kan stadig forekomme i planen i 2012, hvis SELECT har en eksplicit TOP defineret (andre end TOP 100 PROCENT ), men dette garanterer stadig ikke den faktiske indsættelsesrækkefølge af rækker, planen kan så have en anden sortering efter TOP N er etableret for at få rækkerne i grupperet indeksrækkefølge for eksempel.

For eksemplet i dit spørgsmål ville jeg bare justere opkaldskoden for at angive ORDER BY name hvis det er det, det kræver.

Med hensyn til dit sort_id idé fra Bestillingsgarantier i SQL Server det er garanteret, når du indsætter i en tabel med IDENTITY at rækkefølgen disse tildeles vil være i henhold til ORDER BY så du kunne også gøre

DECLARE @Customer TABLE (
  Sort_Id     INT IDENTITY PRIMARY KEY,
  Customer_ID INT,
  Name        INT,
  Expired     BIT )

INSERT INTO @Customer
SELECT Customer_ID,
       Name,
       CASE
         WHEN Expiry_Date < Getdate() THEN 1
         WHEN Expired = 1 THEN 1
         ELSE 0
       END
FROM   Customer
ORDER  BY Name 

men du skal stadig bestille efter sort_id i dine valgforespørgsler, da der ikke er nogen garanteret bestilling uden det (måske dette sort_id fremgangsmåde kan være nyttig i det tilfælde, hvor de originale kolonner, der bruges til bestilling, ikke bliver kopieret ind i tabelvariablen)



  1. gem flere afkrydsningsfeltværdier i databasen ved hjælp af php og mysql

  2. MySQL:Se efter den samme streng i flere kolonner

  3. Inkluderer værdier IKKE FUNDET i MySQL-forespørgselsresultater

  4. Hvad er problemerne med en joinforbindelse mellem to tabeller i to forskellige databaser?