sql >> Databasteknik >  >> RDS >> Sqlserver

Tabell-värderad funktion - Ordning efter ignoreras i utdata

Det var två saker fel med ditt ursprungliga tillvägagångssätt.

  1. När du infogade i tabellen var det aldrig garanterat att ORDER BYINSERT ... SELECT ... ORDER BY skulle vara den ordning som raderna faktiskt infogades.
  2. När du väljer från den garanterar inte SQL Server att SELECT utan en ORDER BY kommer att returnera raderna i vilken ordning som helst, såsom insättningsordning ändå.

Under 2012 ser det ut som om beteendet har ändrats med avseende på punkt 1. Den ignorerar nu generellt ORDER BYSELECT sats som är källan till en INSERT

DECLARE @T TABLE(number int)

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

2008-plan

2012-plan

Anledningen till beteendeförändringen är att SQL Server i tidigare versioner producerade en plan som delades mellan körningar med SET ROWCOUNT 0 (av) och SET ROWCOUNT N . Sorteringsoperatorn var bara där för att säkerställa korrekt semantik om planen kördes av en session med en ROWCOUNT som inte är noll uppsättning. TOPP operatorn till vänster om den är en ROWCOUNT TOP .

SQL Server 2012 producerar nu separata planer för de två fallen så det finns inget behov av att lägga till dessa i ROWCOUNT 0 version av planen.

En sortering kan fortfarande visas i planen under 2012 om SELECT har en explicit TOPP definierade (annat än TOPP 100 PROCENT ) men detta garanterar fortfarande inte faktisk insättningsordning för rader, planen kan då ha en annan sortering efter TOP N är etablerad för att till exempel få raderna i klustrad indexordning.

För exemplet i din fråga skulle jag bara justera anropskoden för att specificera ORDER BY name om det är vad det kräver.

Angående ditt sort_id idé från Beställningsgarantier i SQL Server det garanteras när du infogar i en tabell med IDENTITY att ordningen dessa tilldelas kommer att vara enligt ORDER BY så kan du också göra

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 skulle fortfarande behöva beställa med sort_id i dina valfrågor eftersom det inte finns någon garanterad beställning utan det (kanske detta sort_id tillvägagångssätt kan vara användbart i de fall där originalkolumnerna som används för beställning inte kopieras till tabellvariabeln)



  1. Ta bort en del av en sträng i MYSQL

  2. Xmlparserv2-fel när applikationen distribueras i jboss, installerar Oracle ojdbc-modulen i JBoss för Java-webbapplikation

  3. Hur ser man om en användare är online på en webbplats med php- och mysql-drivna databaser?

  4. Loopar genom $_POST-variabler