sql >> Database >  >> RDS >> Sqlserver

Table-Valued-functie - Order by wordt genegeerd in uitvoer

Er waren twee dingen mis met je oorspronkelijke aanpak.

  1. Bij het invoegen in de tabel werd nooit gegarandeerd dat de ORDER BY op de INSERT ... SELECT ... ORDER BY zou de volgorde zijn waarin de rijen daadwerkelijk zijn ingevoegd.
  2. Bij het selecteren ervan garandeert SQL Server niet dat SELECT zonder een ORDER BY retourneert de rijen in een bepaalde volgorde, zoals de volgorde van invoegen, hoe dan ook.

In 2012 lijkt het alsof het gedrag is veranderd met betrekking tot item 1. Het negeert nu over het algemeen de ORDER BY op de SELECT statement dat de bron is voor een INSERT

DECLARE @T TABLE(number int)

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

2008-abonnement

Abonnement 2012

De reden voor de gedragsverandering is dat in eerdere versies SQL Server één plan produceerde dat werd gedeeld tussen uitvoeringen met SET ROWCOUNT 0 (uit) en SET ROWCOUNT N . De sort-operator was er alleen om de juiste semantiek te garanderen in het geval dat het plan werd uitgevoerd door een sessie met een ROWCOUNT niet nul set. De TOP operator links ervan is een ROWCOUNT TOP .

SQL Server 2012 produceert nu aparte plannen voor de twee gevallen, dus het is niet nodig om deze toe te voegen aan de ROWCOUNT 0 versie van het plan.

Een sortering kan in 2012 nog steeds in het plan verschijnen als de SELECT heeft een expliciete TOP gedefinieerd (anders dan TOP 100 PERCENT ) maar dit garandeert nog steeds niet de daadwerkelijke invoegvolgorde van rijen, het plan kan dan een andere sortering hebben na de TOP N is ingesteld om de rijen bijvoorbeeld in geclusterde indexvolgorde te krijgen.

Voor het voorbeeld in uw vraag zou ik gewoon de aanroepcode aanpassen om ORDER BY name op te geven als dat is wat het vereist.

Met betrekking tot uw sort_id idee van Bestelgaranties in SQL Server het is gegarandeerd bij het invoegen in een tabel met IDENTITY dat de volgorde waarin deze worden toegewezen zal zijn volgens de ORDER BY dus je zou ook kunnen doen

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 

maar je zou nog steeds moeten bestellen met de sort_id in uw selectiequery's, aangezien er geen gegarandeerde bestelling is zonder dat (misschien deze sort_id aanpak kan handig zijn in het geval dat de originele kolommen die voor het ordenen worden gebruikt niet worden gekopieerd naar de tabelvariabele)



  1. Verander de achtergrondkleur van de HTML <area> tag

  2. Hoe programmatisch WHEN en THEN uitvoeren op MySQL-update met Python en Django?

  3. MySQL-verzoek voor combineren en zoeken in 2 tabellen

  4. koppelteken in MySQL-volgorde per clausule