Introduktion till MS SQL Server och T-SQL. Syntax och T-SQL-avtalet


Programmering på T.- Sql

Syntax och T-SQL-avtalet

Regler för bildandet av identifierare

Alla objekt i SQL-servern har namn (identifierare). Exempel på föremål är tabeller, representationer, lagrade procedurer etc. Identifierare kan innehålla upp till 128 tecken, i synnerhet bokstäver, symboler _ @ $ # och siffror.

Det första tecknet ska alltid vara alfabetet. Särskilda namngivningssystem används för variabla och tillfälliga tabeller. Objektnamnet kan inte innehålla mellanslag och sammanfalla med SQL Server reserverat sökord, oavsett det använda symbolregistret. Genom att skriva ut identifierare till kvadratkonsoler kan förbjudna tecken användas i objektnamn.

Slutförande av instruktionen

Ansi SQL-standarden kräver rummet i slutet av varje punkt med en kommatecken. Samtidigt, när programmering i T-SQL-språket, är en kommatecken inte nödvändig.

Kommentarer

T-SQL-språk tillåter användning av två stilar: Anci och språk S. Den första börjar med två bindestreck och slutar i slutet av linjen:

Detta är en enstaka Ansi-stilkommentar

Också ansi stil kommentarer kan införas i slutet av instruktionslinjen:

Välj stadsnamn. - Återvinningsbara kolumner

Från staden. - Källbord

Där idcity \u003d 1; - Begränsa på linjerna

SQL Editor kan tillämpa och ta bort kommentarer i alla valda linjer. För att göra detta, välj lämpliga kommandon i menyn. Redigera eller på verktygsfältet.

Kommentarer från språkstil börjar med ett snedstreck och asterisk (/ *) och slutar med samma symboler i omvänd ordning. Denna typ av kommentarer är bättre att använda för att kommentera strängar, till exempel rubriker eller stora testfrågor.

multilinje

kommentarer

En av de viktigaste fördelarna med stilen kommentarer är att flera linjer förfrågningar i dem kan utföras, utan att ens vara obekväma.

T-SQL-paket

Frågan kallas en T-SQL-instruktion, och paketet är deras uppsättning. Hela sekvensen av förpackningsinstruktionerna skickas till servern från klientprogram som en helhet.

SQL Server anser hela paketet som en arbetsenhet. Närvaron av ett fel åtminstone i en instruktion leder till omöjligheten att utföra hela paketet. Samtidigt kontrollerar grammatikets parse inte namnen på föremål och system, eftersom det kan förändras under genomförandet av instruktionen.

SQL Script File och Query Analyzer-fönstret kan innehålla flera paket. I det här fallet delar alla paket terminatorernas sökord. Som standard är det här sökordet, och det borde vara det enda i strängen. Alla andra tecken (även kommentarer) neutraliserar paketseparatorn.

Debugging T-SQL

När SQL-redigeraren upptäcker ett fel visas det tecken och radnummer i förpackningen. Genom att dubbelklicka på felet kan du omedelbart flytta till motsvarande sträng.

I förvaltningsstudioverktyget innehåller SQL Server 2005-versionen inte T-SQL-språkfelsökaren, den är närvarande i det visuella studiopaketet.

SQL Server erbjuder flera kommandon som underlättar paketfelsökning. I synnerhet skickar utskriftskommandot ett meddelande utan att generera en resulterande dataset. Utskriftskommandot kan användas för att spåra paketets slag. När Query Analyzer är i rutnätet, utför följande paket:

Välj stadsnamn.

Från staden.

Där idcity \u003d 1;

Skriva ut "Check Point";

Den resulterande dataset kommer att visas i rutnätet och bestå av en rad. Samtidigt visas följande resultat i fliken "Meddelanden":

(Rader behandlade: 1)

Kontrollpunkt

Variabler

Variables T-SQL skapas med hjälp av det förklara kommandot med följande syntax:

Förklara @ name_named type [,

@ Name_Name Type_Data, ...]

Alla namn på lokala variabler bör börja med @ symbol. Till exempel, för att förklara USTR-lokalvariabel, som lagrar upp till 16 Unicode-tecken, kan du använda följande instruktioner:

Förklara @ ... Varchar (16)

De datatyper som används för variabla data sammanfölls exakt med befintliga i tabeller. I ett förklaring kan flera variabler listas över kommatecken. I synnerhet skapas två heltalsvariabler A och B i följande exempel:

Deklarera.

@a int

@b int

Sortimentet av variabler (dvs deras liv) gäller endast det aktuella paketet. De standardvariabla standardinställningarna innehåller tomma nollvärden och innan införandet i uttrycket bör initialiseras.

Ställ in värdena för variabler

För närvarande finns det två sätt att ställa in värdet på det rörliga värdet i SQL - för detta ändamål kan du använda Select eller Set-satsen. Ur meningen med de utförda funktionerna agerar dessa operatörer nästan densamma, inte räknar att select-satsen tillåter det ursprungliga uppdragsvärde från tabellen som anges i SELECT-satsen.

Set-satsen används vanligtvis för att ställa in värdena på variabler i denna blankett, som ofta finns på procedurspråk. Som typiska exempel på att applicera den här operatören kan du ange följande:

Set @a \u003d 1;

Set @b \u003d @a * 1.5

Observera att alla dessa operatörer är direkt implementerade genom uppdragsverksamhet där antingen uttryckligen specificerade värden används eller andra variabler. Med hjälp av det säkra uttalandet är det omöjligt att tilldela ett rörligt värde som erhållits med hjälp av frågan; Frågan måste utföras separat och först efter det att det erhållna resultatet kan tilldelas med hjälp av det inställda uttalandet. Till exempel orsakar ett försök att utföra en sådan operatör ett fel:

Förklara @c int

Set @c \u003d räkna (*) från staden

Välj @c.

och nästa operatör är fullt framgångsrik:

Förklara @c int

SET @C \u003d (Välj räkning (*) från stad)

Välj @c.

Select-uttalandet brukar användas för att tilldela värden med variabler om den informationskälla som måste sparas i en variabel är en fråga. Till exempel, de åtgärder som implementeras i koden ovan är mycket oftare implementerade med hjälp av select-satsen:

Förklara @c int

Välj @c \u003d räkna (*) från staden

Välj @c.

Observera att den här koden är något tydligare (i synnerhet är det mer laconiskt, även om det utför samma åtgärder).

Det är således möjligt att formulera följande allmänt accepterade avtal om användningen av den andra operatören.

Set-satsen används om en enkel uppgiftsoperation måste utföras, d.v.s. Om det tilldelade värdet redan anges uttryckligen i form av ett visst värde eller i form av någon annan variabel.

  • Select-uttalandet tillämpas om uppdraget av variabelns värde måste baseras på begäran.

Använda variabler i SQL-frågor

En av de användbara egenskaperna hos T-SQL-språket är att variabler kan användas i frågor utan att behöva skapa komplexa dynamiska linjer som är inbäddade variabler i programkoden. Dynamisk SQL fortsätter sin existens, men ett enda värde kan ändras enklare - med hjälp av en variabel.

Varhelst ett uttryck kan användas i frågan kan en variabel användas. Följande exempel visar användningen av en variabel i var mening:

Förklara @idprod int;

Set @idprod \u003d 1;

VÄLJ

Från produkt.

Var IDPROD \u003d @IDPROD;

Globala systemvariabler

SQL Server har mer än trettio globala variabler som inte har parametrar som bestäms och stöds av systemet. Alla globala variabler har ett prefix i form av två tecken @. Du kan extrahera någon av dem med en enkel valfråga, som i följande exempel:

Välj @@ anslutningar

Den använder de globala variabla @@ -anslutningarna för att extrahera antalet anslutningar till SQL Server eftersom programmet startas.

Bland de vanligaste systemvariablerna kan följande noteras:

  • @@ Error - innehåller ett felnummer som inträffade vid utförande av den senaste T-SQL-operatören i den aktuella anslutningen. Om felet inte detekteras innehåller 0. Värdet av denna systemvariabel installeras efter att ha utfört varje nästa operatör. Om du vill spara det värde som finns i det, bör detta värde överföras till den lokala variabeln omedelbart efter att ha utfört den operatör för vilken felkoden måste sparas.
  • @@ Identity - innehåller det sista identifieringsvärdet som sätts in i databasen som ett resultat av utförandet av den sista insatsoperatören. Om insatsens sista uttalande inte hade ett identifieringsvärde, innehåller systemvariabeln @@ identitet null. Detta uttalande är fortfarande rättvist, även om frånvaron av ett identifieringsvärdet orsakades av en nödsituation vid utförandet av en operatör. Och om med hjälp av en operatör, utförs flera insatser, endast det sista identifieringsvärdet tilldelas denna systemvariabel.
  • @@ rowcount är en av de mest använda systemvariablerna. Returnerar information om antalet linjer som påverkas av den sista operatören. Vanligtvis används den för att kontrollera andra fel än de som refererar till kategorin programkörningsfel. Om exempelvis programmet upptäcker att efter samtalet för att utföra den raderade operatören med den design, är antalet berörda priser noll, då kan det konstateras att något oväntat hände. Därefter kan felmeddelandet aktiveras manuellt.

! Det bör noteras att med SQL Server 2000-versionen är globala variabler vanliga att ringa funktioner. Namnet Global Shot Down-användare med en känsla, så att du kan tro att omfattningen av sådana variabler är bredare än den för lokala. Den globala variabeln hänförde sig ofta felaktigt möjligheten att lagra information, oavsett om det ingår i paketet eller inte det, naturligtvis inte motsvarade verkligheten.

Kommandokontroller. Programvarudesign

På T-SQL-språket tillhandahålls det mesta av det klassiska procedurella sättet att hantera programkörning av programmet, inkl. Villkorlig design och cykler.

OperatörOM. . . ANNAN.

Om operatörer. . .ESe operera i T-SQL-språk i princip samma som i alla andra programmeringsspråk. Den totala syntaxen för denna operatör har följande formulär:

Om logiskt uttryck

SQL-instruktion Jag börjar SQL-blockinstruktioner

SQL-instruktion | Börja blockera SQL-instruktionerna slutar]

Som ett logiskt uttryck kan nästan vilket uttryck som helst specificeras, resultatet av beräkningen av vilket leder till återlämnande av det booleska värdet.

Man bör komma ihåg att endast den operatör som direkt följer om operatören (närmast den direkt) anses vara beaktad. I stället för en operatör kan du ge utförandet av flera operatörer genom att kombinera dem i kodblocket med början ... Slutdesign.

I exemplet nedan är IF-tillståndet inte exekverat, vilket förhindrar utförandet av följande operatör.

Om 1 \u003d 0

Skriv ut "första raden"

Skriv ut "andra sträng"

Med det frivilliga kommandot kan du ange den instruktion som ska utföras om IF-villkoret inte exekveras. Gilla om, om den andra operatören bara hanterar följande kommando eller kod för fången av fånge mellan att börja ... slutet.

Trots det faktum att om operatören är begränsad, kan dess förslag villkor innefatta kraftfulla funktioner, som det där förslaget. I synnerhet är detta ett om det existerar () uttryck.

Uttrycket om det existerar () använder som ett tillstånd närvaron av vilken sträng som helst som returneras av valdinstruktionen. Eftersom några rader söks kan listan över kolumner i select-satsen bytas ut med en asterisk. Denna metod fungerar snabbare än att kontrollera @@ rowcount\u003e 0, eftersom det inte kräver det totala antalet rader. När minst en rad uppfyller villkoret om det existerar () kan begäran fortsätta att utföra.

I följande exempel används en om det existerar uttryck för att kontrollera närvaron av några beställningar från klienten 1 innan den tar bort den från basen. Om den här klienten har information minst en order, görs inte radering.

Om det finns (välj * varifrån IDCUST \u003d 1)

Skriva ut "Kan inte ta bort klienten eftersom det finns relaterade poster i databasen"

ANNAN.

Var IDCUST \u003d 1

Skriva ut "Radering utfördes framgångsrik"

OperatörerMedan Bryta I.Fortsätta.

Medan operatören i SQL-språk fungerar på många sätt såväl som på andra språk som programmeraren vanligtvis måste fungera. Faktum är att i den här operatören före starten av varje passage längs cykeln kontrolleras ett visst tillstånd. Om, före nästa passage av cykeln, leder valideringen av förhållandena till värdet av sant, cykelpasset utförs, annars är utförandet av operatören färdigställd.

Medan operatören har följande syntax:

Medan logiskt uttryck

SQL-instruktion I.

SQL-instruktionsblock

Naturligtvis, med hjälp av underlaget, är det möjligt att endast utföra en operatör i cykeln (analogt med hur om operatören vanligtvis används), men i praktiken av underdesignen, följt av startblocket. . .Varande, som motsvarar operatörens fulla format, är sällsynta.

Brottoperatören gör att du omedelbart kan lämna cykeln, inte förväntar sig hur passagen till slutet av cykeln kommer att slutföras och det villkorliga uttrycket kommer att inträffa.

Fortsätt-operatören gör att du kan avbryta en separat iteration av cykeln. Du kan kortfattat beskriva den fortsatta operatörens åtgärd så att den ger övergången till början av startcykeln. Omedelbart efter fortsatt operatör finns i slingan, oavsett var den är belägen, det finns en övergång till början av cykeln och beräkna det villkorliga uttrycket (och om värdet av detta uttryck inte längre är äkta, utgång från cykeln).

Följande korta skript visar användningen av en stund operatör för att skapa en cykel:

Förklara @temp int;

Set @temp \u003d 0;

Medan @temp.< 3

Börja.

Skriv ut @temp;

SET @TEMP \u003d @TEMP + 1;

Här i cykeln ökar heltalet variabelt @temp från 0 till 3 och vid varje iteration visas dess värde på skärmen.

OperatörLämna tillbaka.

Returutlåtandet används för att stoppa utförandet av paketet, och därför det lagrade proceduren och utlösaren (diskuteras i följande laboratorieeklasser).

  • Överföra

Det är inte tillräckligt att skriva koden väl läsbar: den bör också snabbt springa.

Det finns tre grundläggande regler för att skriva en sådan T-SQL-kod som fungerar bra. De är kumulativa - uppfyllandet av alla dessa regler kommer att ha en positiv effekt på koden. Hoppet eller förändringen av någon av dem kommer sannolikt att leda till en negativ inverkan på din kod.

  • Skriv, baserat på lagringsstrukturen: Om du lagrar datetimdata, använd DateTime, inte Varchar eller något annat.
  • Skriv, baserat på tillgängligheten av index: Om index är byggda på bordet, och de ska vara där, skriv koden så att den kan använda alla fördelar som tillhandahålls av dessa index. Se till att klusterindexet, och för varje tabell det bara kan vara en, används på det mest effektiva sättet.
  • Skriv för att hjälpa Query Optimizer: Query Optimizer är en härlig del av DBMS. Tyvärr kan du mycket svårt sitt arbete genom att skriva en förfrågan om att han är "svår" att demontera, till exempel, innehållande efterföljande visningar - när en vy tar emot data från den andra, och sedan från den tredje - och så vidare. Ta dig tid att förstå hur Optimizer fungerar och skrivsförfrågningar så att det kan hjälpa dig, och inte skada.
Det finns flera typiska fel som människor erkänner i sin kod på T-SQL - inte begå dem.

Använda felaktiga datatyper

I teorin, undvik det här felet är väldigt enkelt, men i praktiken är det ganska ofta. Till exempel använder du datatyp i din databas. Använd den i dina parametrar och variabler! Ja, jag vet att SQL-servern kan implicit korrigera en typ av data till en annan. Men när en implicit typomvandling uppstår, eller du själv citerar typen av kolumndata till en annan typ, utför du konverteringen för hela kolumnen. När du utför den här konverteringen för en kolumn i vartrutan eller i anslutningsförhållandet - kommer du alltid att se tabellskanningen (tabellskanning). Enligt den här kolumnen kan ett utmärkt index byggas, men eftersom du kastar för de värden som är lagrade i den här kolumnen för att jämföra, till exempel, det datum som lagras i den här kolumnen, med den typ av char som du använde i skicket Indexet kommer inte att användas.

Tro inte? Låt oss titta på den här förfrågan:

Välj e.BusinessEntityID, e.nationalidnumber från HumanResources.employee som e där e.nationalidnumber \u003d 112457891;
Välskriven och mycket enkel. Det bör täckas av det index som skapats på denna tabell. Men här är exekveringsplanen:

Denna fråga utförs ganska snabbt och bordet är litet, så att endast fyra läsningar kommer att krävas för att skanna indexet. Var uppmärksam på ett litet utropstecken i Select-uttalandet. Om du vänder dig till dess egenskaper kommer vi att se:

Höger. Detta är en varning (ny i SQL Server 2012) att typomvandlingen utförs som påverkar genomförandet. Kortfattat - det beror på att frågan använder en ogiltig datatyp:

Välj e.BusinessEntityID, e.nationalidnumber från humanresources.employee som e var e.nationalidnumber \u003d "112457891";
Och vi får en sådan frågeformulär:

Och här används endast två läsoperationer, istället för fyra. Och ja, jag förstår att jag gjorde och så snabbt är frågan lite snabbare. Men vad skulle hända om miljontals linjer hölls i bordet? Ja, då skulle jag vara en hjälte.

Använd rätt datatyper.

Använder funktioner vid sammanställning av anslutningsförhållanden och i var uttryck

Tala om funktioner - de flesta av de funktioner som används vid anslutningsförhållanden eller där uttryck, som du, som ett argument, passerar kolumnen, stör rätt användning av index. Du kommer att se hur långsammare förfrågningarna körs, där de funktioner som mottas som argument används. Till exempel:

Välj adressLine1, A.Addressline2, A.City, A.StateProvinceid från person. Atddress som en var "4444" \u003d vänster (A.Addressline11, 4);
Den här funktionen, vänster, tar emot en kolumn som ett argument, som hälls i denna utföringsplan:

Som ett resultat utförs 316 läsoperationer för att hitta nödvändiga uppgifter, och det tar 9 millisekunder (jag har mycket snabba skivor). Allt eftersom "4444" måste jämföras med varje rad som returneras av den här funktionen. SQL Server kan inte ens skanna bordet, det måste utföras till vänster för varje rad. Men du kan göra något så här:

Välj AADDRESSLINE1, A.AddressLine2, A.City, A.StateProvinceid från person. Atddress som en där a.Addressline1 som "4444%";
Och här ser vi en helt annan exekveringsplan:

För att utföra frågan kräver 3 läsoperationer och 0 millisekunder. Tja, eller kan det vara 1 millisekund, för objektivitet. Detta är en stor ökning av prestanda. Och allt eftersom jag använde en sådan funktion som kan användas för att söka efter index (tidigare kallades det Sargeable - onödigt, i allmänhet Ordet: SARG - sök argument, om den svåra funktionen är en kolumn som ett argument till det och kommer fortfarande att användas index sökning, om inte svängbart - ALAS, kommer indexsökningen alltid att användas - ca. översättare). Använd i alla fall inte funktioner där uttryck eller söktermer, eller använd endast de som kan användas i läget för indexet.

Med hjälp av multi-sedlar udf

Multi-Statement UDF i den ryska utgåvan av MSDN översätter ungefär som "användardefinierade funktioner, bestående av flera instruktioner, men det låter, enligt min mening, på något sätt konstigt, så jag försökte undvika översättning av denna term i texten - ca . översättare

Faktum är att de kör dig i fällan. Vid första anblicken tillåter denna underbara mekanism oss att använda T-SQL som ett riktigt programmeringsspråk. Du kan skapa dessa funktioner och kalla dem en av de andra och koden kan användas igen, inte det faktum att dessa gamla lagrade procedurer. Det här är otroligt. Så länge du inte försöker köra den här koden på en stor mängd data.

Problemet med dessa funktioner är att de är byggda på tabellvariabler. Bordsvariabler är en mycket cool sak om du använder dem för destination. De har en tydlig skillnad från tillfälliga tabeller - statistik är inte byggd på dem. Denna skillnad kan vara mycket användbar, och kanske ... Döda dig. Om du inte har statistik förutsätter optimeringaren att varje förfrågan som körs till en tabellvariabel eller UDF kommer att returnera endast en rad. En (1) sträng. Det är bra om de verkligen återvänder flera linjer. Men en dag kommer de att återvända hundratals eller tusentals rader och du bestämmer dig för att ansluta en UDF på den andra ... Prestationen kommer att falla väldigt, mycket snabbt och mycket, väldigt mycket.

Exemplet är tillräckligt bra. Här är några UDF:

Skapa funktion dbo.salesinfo () Returer @return_variable tabell (SalesOrdoDid int, orderdatum DateTime, säljare do.ordernumber, kontoumber dbo.AccountNumber, fraktcities nVarchar (30)) som början; Infoga i @return_variable (SalesOrderID, orderdatum, säljare, fraktköp) Välj Soh.Salesorderid, Soh.orderdate, Soh.Salespersonstid, Soh.PurchaseOrnNumber, Soh.AccountNumber, A.City från Sales.SalesorderHeader AS SOH Gå med i person. Adress som A på SOH.SHIPTOADDRESSID \u003d A.Addressid; Lämna tillbaka; Slutet; Gå Skapa funktion dbo.SalesDetails () Returns @return_variable tabell (SalesOrdoDid int, SalesorderDetailid int, OrderQty Smallint, UnitPrice Pengar) som början; Infoga i @return_variable (SalesOrtId, Salesordetailid, OrderQty, UnitPrice) Välj Sod.salesorderid, Sod.SaleesorderDetailid, Sod.OrtSQTY, SOD.UnitPrice från Sales.SalesorderDetail som SOD; Lämna tillbaka; Slutet; Gå Skapa funktion dbo.comBinedSalesInfo () Returns @return_variable tabell (säljare (30), orderdata dateTime, inköpsordernumber dbo.ordernumber, concountnumber dbo.accountNumber, orderQusty smallint, unitprice pengar) som början; Infoga i @return_variable (säljareOnd, fraktcitexity, orderdate, inköpsorder, bearbetningsnummer, orderQuate, unitPrice) Välj si.Salesperson, si.ShippingCity, si.orderdate, si.purchaseordernumber, si.AccountNumber, SD.Ortorqty, SD.UnitPrice från DBO. SalesInfo () AS SI Join Dbo.SalesDetails () som SD på si.salesorderid \u003d sd.salesorderid; Lämna tillbaka; Slutet; Gå.
Utmärkt struktur. Det låter dig utgöra mycket enkla förfrågningar. Tja, till exempel här:

Välj csi.orderdate, csi.purcoutnumber, csi.accountNumber, csi.orderqty, csi.unitpris från dbo.combinedsalesinfo () som csi där csi.salesmanid \u003d 277 och csi.shippingcity \u003d "Odessa";
En, mycket enkel förfrågan. Här är hans exekveringsplan, lika enkelt:

Det är bara 2,17 sekunder det kör, returnerar 148 linjer och använder 1456 läsoperationer. Observera att vår funktion har nollkostnad och bara skanna ett bord, tabelliveriabeln påverkar kostnaden för begäran. Hmm, sanning? Låt oss försöka se vad som är dolt bakom UDF-exekveringsoperatören med nollkostnad. Den här frågan får en cachefunktionsplan:

Välj deqp.Query_Plan, dest. Text, substring (dest. .dm_exec_query_plan (deqs.plan_handle) som deqp cross applicera sys.dm_exec_sql_text (deqs.sql_handle) som dest där dqp.objectid \u003d objektiv_id ("dbo.combinedsalesinfo");
Och det är vad som händer där i själva verket:

Wow, det verkar här Det finns flera fler få funktioner och skanningar av bord, som nästan, men fortfarande inte riktigt, gör ingenting. Plus, Hash Match Connection Operator, som skriver i Tempdb och har mycket värde vid utförande. Låt oss se utföringsplanen för en annan UDF:

Här! Och nu ser vi clustered indexskanning, där ett stort antal linjer skannas. Detta är inte längre bra. I allmänhet, i hela situationen, verkar UDF mindre och mindre attraktiv. Vad händer om vi, ja, jag vet inte direkt, försök bara direkt för att kontakta borden. Så, till exempel:

Välj soh.orderdate, soh.purchaseordernumber, soh.accountNumber, sod.orderqty, sod.unitpris från sales.salesorderHeader som soh gå med sales.salesorderdetail som sod på soh.salesorderid \u003d sod.salesorderid Gå med i person. Address som ba på soh.billtoaddressid \u003d Ba.addressid gå med i personen
Nu, genom att slutföra den här förfrågan, kommer vi att få absolut samma data, men bara 310 millisekunder, och inte för 2170. Plus, SQL Server kommer endast att utföra 911 läsoperationer, och inte 1456. Ärligt talat är det väldigt lätt att få prestationsproblem använder UDF.

Aktivera "Work Snabbare!" Inställning: Använda "Dirty Readings"

Återvänder till det förflutna, till de gamla datorerna med 286-processorer ombord, kan du komma ihåg det av ett antal skäl, på frontpanelen hade de "turbo" -knappen. Om du av misstag "pressade" henne, började datorn omedelbart sakta ner. Således insåg du att vissa saker alltid skulle inkluderas för att säkerställa maximal bandbredd. På samma sätt ser många människor på isoleringsnivån Read_uncommitted och Hins No_Lock, som på Turbo-knappen för SQL Server. När du använder dem, var noga med - nästan vilken begäran som helst och hela systemet kommer att bli snabbare i allmänhet. Detta beror på det faktum att när läsning inte kommer att vara överlagd och inga blockeringar kommer att kontrolleras. Mindre lås - snabbare resultatet. Men…

När du använder Read_Uncommitted eller No_Lock i dina frågor, stöter du på smutsiga avläsningar. Alla förstår vad det betyder att du kan läsa "hunden" och inte "katt", om det just nu är utfört, men uppdateringsoperationen har ännu inte slutförts. Men förutom detta kan du få mer eller mindre linjer än faktiskt, såväl som dubbla rader, eftersom datasidorna kan röra sig under din förfrågan, och du inte pålägger några lås för att undvika det. Jag vet inte hur du har, men de flesta av de företag där jag arbetade, förväntade mig att de flesta ansökningar om de flesta system kommer att återvända holistiska data. Samma förfrågan med samma parametrar som utförs på samma uppsättning data bör ge samma resultat. Endast inte om du använder NO_LOCK. För att se till att jag råder dig att läsa det här inlägget.

Orimlig användning av tips i frågor

Människor fattar snabbt ett beslut om användningen av tips. Den vanligaste situationen är när antydan hjälper till att lösa en, mycket sällan hittat problem, på en av förfrågningarna. Men när människor ser en betydande ökning av prestanda på denna begäran ... börjar de omedelbart peka det i allmänhet överallt.

Till exempel tror många att det är det bästa sättet att ansluta tabeller. De kommer till denna slutsats eftersom det oftast finns i små och snabba frågor. Därför bestämmer de sig med att tvinga SQL-servern att använda slingan med. Det är inte alls svårt:

Välj S. Som StoreName, P.LastName + "," + P.FirstName from Sales.Store AS S Gå med i Sales.SalesPerson AS SP ON S.SALESSONOD \u003d SP.BusinessEntityId .Person som p på e.businessentityid \u003d p.businessentityid-alternativet (slingan med);
Denna begäran utförs 101 millisekund och gör 4115 läsoperationer. I allmänhet är det inte dåligt, men om vi tar bort denna ledtråd, kommer samma fråga att slutföras för 90 millisekunder och producerar endast 2370 avläsningar. Ju mer systemet är laddat, desto mer uppenbart kommer att vara effektiviteten av frågan utan användning av tips.

Och här är ett annat exempel. Människor skapar ofta ett index på bordet och väntar på att det ska lösa problemet. Så vi har en förfrågan:

Välj * Från inköp.purchaseorderheader som POH där POH.PurchaseOderID * 2 \u003d 3400;
Problemet är att när du utför en kolumnkonvertering, kommer inget index att användas tillräckligt. Prestationsdroppar eftersom klusterindexet skannas. Och så när människor ser att deras index inte används, gör de det här:

Välj * Från inköp.purchaseorderheader som POH med (PK_PurchaseOderDeHeader_PurchaseOrtID)) där Poh.PurchaseOderID * 2 \u003d 3400;
Och nu får de skanning som valts av dem, inte kluster, index, så att indexet "används" är sant? Men query-prestanda ändras - nu istället för 11 läsoperationer, 44 körs (körtid för både 0 millisekunder, eftersom jag har riktigt snabbskivor). "Används" används, men inte alls förväntas. Lösningen på detta problem är att skriva om begäran på detta sätt:

Välj * Från inköp.PurchaseorderHeader POH där inköpsOrderID \u003d 3400/2;
Nu föll antalet läsoperationer till två, eftersom sökandet efter indexet används - indexet används korrekt.

Tips i frågor ska alltid tillämpas sist, efter att alla andra möjliga alternativ testades och inte gav ett positivt resultat.

Användning av Line-to-Line Query Execution Resultatbehandling ('rad genom att agonisera rad' bearbetning)

Konstruktionsbearbetningen utförs med hjälp av markörer eller operationer i undercykeln, i stället för uppsättningar över uppsättningar. När du använder dem är prestationen väldigt och mycket låg. Markörer används vanligtvis av två skäl. Den första av dessa är utvecklare som är vana vid att använda linjen bearbetning i sin kod, och den andra - utvecklare som kommer med Oracle, som tror att markörer är en bra sak. Oavsett orsaken, döda prestanda för roten.

Här är ett typiskt exempel på misslyckad användning av markören. Vi måste uppdatera färgen på de produkter som valts med ett specifikt kriterium. Det uppfinns inte - det är baserat på koden som jag en gång måste optimeras.

Börja transaktionen förklara @Name NVARCHAR (50), @Color NVarchar (15), @Weight decimal (8, 2) Förklara BigUpdate-markören för vald P. , p.color, s. Från produkt. Produkt som P; Öppna bigupdate; Hämta nästa från bigupdate int @name, @Color, @weight; Medan @@ fetch_status \u003d 0 börja om @weight< 3 BEGIN UPDATE Production.Product SET Color = "Blue" WHERE CURRENT OF BigUpdate END FETCH NEXT FROM BigUpdate INTO @Name, @Color, @Weight ; END CLOSE BigUpdate ; DEALLOCATE BigUpdate ; SELECT * FROM Production.Product AS p WHERE Color = "Blue" ; ROLLBACK TRANSACTION
I varje iteration gör vi två läsoperationer, och antalet produkter som uppfyller våra kriterier beräknas av hundratals. På min bil, utan belastning, är exekveringstiden mer än en sekund. Det är helt oacceptabelt, särskilt sedan omskriven denna förfrågan är väldigt enkel:

Börja transaktionsuppdatering produktion.Produkt set color \u003d "blue" var< 3 ; ROLLBACK TRANSACTION
Nu är endast 15 läsning och exekveringstid bara 1 millisekund. Skratta inte. Människor skriver ofta en sådan kod och ännu värre. Markörer är en sådan sak som bör undvikas och användas bara där det är omöjligt att göra utan dem - till exempel i serviceuppgifter, där du behöver "springa" med olika tabeller eller databaser.

Orimlig användning av kapslade representationer

Presentationer som hänvisar till de synpunkter som förbinder med de synpunkter som hänvisar till andra synpunkter som ansluter till visning ... Presentation är bara en förfrågan. Men eftersom de kan behandlas med båda tabellerna kan människor börja tänka på dem som bord. Och förgäves. Vad händer när du ansluter en vy med en annan, med hänvisning till den tredje idén och så vidare? Du skapar bara en jävla utmanande sökplan. Optimeraren kommer att försöka förenkla det. Det kommer att försöka planer där inte alla tabeller används, men tiden att arbeta med valet av planen är begränsad och den mer komplexa planen som den kommer att få, desto mindre sannolikt kommer det i slutändan att ha en ganska enkel exekveringsplan. Och prestationsproblem kommer att vara praktiskt taget oundvikligt.

Här, till exempel en sekvens av enkla frågor som bestämmer visningarna:

Skapa visa dbo.salesinfoview som sed soh.salesorderid, soh.orderdate, soh.salesmanid, soh.purchaseordernumber, soh.AccountNumber, a.City som fraktcitic from sales.salesorderHeader som Soh.Shiptoaddressid \u003d a .Addressid; Skapa Visa dbo.SalesDetailsView AS SEAR SOD.Salesorderid, sod.salesordetailid, sod.orderqty, sod.unitprice från sales.salesorderdetail som SOD; Skapa Visa dbo.combininSalesinfoview som sedel si.salesmanid, si.shippingcity, si.orderdate, si.purchaseordernumber, si.accountNumber, sd.orderqty, sd.unitpris från dbo.salesinfoview som si med dbo.salesDetailsView som SD på si.salesderid \u003d Sd.salesorderid;
Och här har författaren till texten glömt att ange begäran, men det leder det i kommentarerna (ca. översättare):
Välj csi.orderdate från dbo. Cominsalesinfoview csi där csi.salesmanid \u003d 277
Som ett resultat utförs vår begäran 155 millisekunder och använder 965 läsoperationer. Här är hans exekveringsplan:

Det ser bra ut, särskilt eftersom vi får 7000 linjer, så det verkar vara okej. Men vad händer om vi försöker uppfylla denna begäran:

Välj Soh.orderdate från Sales.SalesorderHeader som SOH där Soh.SalesPersonID \u003d 277;
Och nu utförs förfrågan för 3 millisekunder och använder 685 läsoperationer - helt annorlunda. Och här är hans genomförandeplan:

Eftersom du kan se till att optimeringaren inte kan kasta ut alla extra tabeller som en del av begäran om att förenkla begäran. Därför finns det i den första exekveringsplanen två onödiga operationer - indexskanning och hash match, samlar data tillsammans. Du kan spara SQL Server från onödigt arbete genom att skriva denna begäran utan att använda idéer. Och kom ihåg - Det här exemplet är väldigt enkelt, de flesta av de önskemål i det verkliga livet är mycket mer komplicerade och leder till mycket mer prestationsproblem.

I kommentarerna har denna artikel en liten tvist, vars essens är det bidraget (författaren till artikeln), det verkade uppfylla sina önskemål inte i standarddatabasen för äventyrslager, men på en liknande databas, men med en något Olika struktur, på grund av vad exekveringsplanen är "icke-optimal" frågan som ges i den sista sektionen skiljer sig från vad som kan ses genom att göra ett experiment själv. Cirka. översättare.
Om någonstans var jag onödigt snett (och jag kan) och texten är svår för att förstå, eller du kan erbjuda mig den bästa formuleringen av någonting - med glädje kommer du att lyssna på alla observationer.

SQL-syntax

I det här avsnittet beskrivs de viktigaste skillnaderna i SQL-språksyntax som används av Firebird och MS SQL.

Firebird och MS SQL DBMS kan referera till databasobjekten (tabeller, fält etc.) för deras namn direkt om namnen på objekt inte innehåller mellanslag och andra tecken oacceptabla i en direktlänk (till exempel icke-länande bokstäver). För att använda luckor och andra SQL DBMS-tecken använder MSQL kvadratkonsoler, [och], och Firebird DBMS använder dubbla citat ". En annan skillnad är möjligheten att använda MS SQL-kretsar för att referera till objektet: base_data .theldeel_abject.object. Firebird DBMS tillåter inte sådan notering.

Uppmärksamhet

MS SQL DBM använder register-och-beroende objektnamn om du har valt användningen av diskussionerna om symbolregistret; Annars registrerar objektens namn oberoende. Roligt? Inte riktigt...

ledtråd

MS SQL DBMS kan arbeta med identifierare vars namn är inneslutna i dubbla citat, men som standard är den här funktionen endast tillgänglig när du öppnar genom OLE DB och ODBC, men inte när du öppnar via DB-bibliotek. Av denna anledning bör sådana metoder undvikas.

DBMS MS SQL 7 och över stöder uppdaterade anslutningar (anslutningar) (uppdatering, radering, infoga). Firebird DBMS känner inte igen sådan syntax.

Typer av Danya, naturligtvis skiljer sig. Även om båda DBMS har en allmän delmängd av de vanligaste typerna. Denna fråga orsakar sällan problem vid överföring av en databas.

Låsta inbäddade funktioner. De flesta av de inbyggda MS SQL DBMS-funktionerna kan bytas ut med Firebird DBM med användardefinierade funktioner (UDF).

Formaten för indikationen av strängkonstanterna för datum är särskiljande. DBMS Firebird accepterar rader av olika format, oavsett vilken plattform som används. MS SQL DBMS använder i sin tur kombinationen av server-oberoende, serverplattformsformat och inställningsformat för klientanslutning. Dessutom administreras SQL DBMS-åtkomstmetoder vanligtvis en eller två nivåer där strängkonstanten kan omvandlas till ett datum på ett eller annat sätt.

I MS SQL DBMS kan du definiera ett större antal miljövariabler än i Firebird DBMs, men det vanligaste kan hittas i Firebird DBM (extrahera identifierare och användarnamn). Den enda viktiga variabeln som saknas i Firebird DBMS är en variabel som returnerar antalet strängar av den sista operationen (från version 1.5 i Firebird DBMS, en sådan variabel introduceras - ca. över.).

En viktig skillnad var att Firebird 1.0 DBMS inte stödde falloperatören MS SQL. Ibland var det möjligt att ersätta sin funktionalitet med det lagrade proceduren. Från version 1.5 stöder Firebird DBMS användningen av falloperatör.

En liten skillnad mellan DBMS är också att MS SQL DBMS inte använder separatorer för operatörer, som kan fungera som en källa till knappt upptäckta fel i övergång, speciellt vid användning av flera parentes. Firebird DBMS i skript kräver att varje operatör har en kommatecken (om en annan separator inte är definierad - prim. Över.), Så fel är lättare att upptäcka.

Både DBMS MS SQL och Firebird support kommentarer som ingåtts mellan separatorer / * och * /. DBMS MS SQL stöder också syntaxen "två bindestreck" - för en enstaka kommentar. Vissa Firebird DBMS-verktyg stöder också en sådan syntax.

Medan

Den medan operatören finns i både DBMS Firebird och MS SQL, men med vissa skillnader. Det finns ingen paus eller fortsätta operatörer, men de kan emuleras med hjälp av ytterligare strukturer. Det finns också en liten skillnad i den använda syntaxen: Firebird DBMS kräver närvaron av ett nyckelord gör efter ett cykeltillstånd. Jämför följande ekvivalenta delar av koden.

/ * Firebird Syntax. * / Medan jag< 3) DO BEGIN i = i + 1; j = j * 2; END /* Синтакс MS SQL. */ WHILE (i < 3) BEGIN SET @i = @i + 1 SET @j = @j * 2 END

Lämna tillbaka.

Returoperatören i MS SQL DBMS returnerar värdet på en heltal variabel och slutar utförandet. Firebird DBMS existerar ett exit uttalande som överför kontrollen till det slutliga ändrade förfarandet. Det finns dock ingen dold returnerad variabel här, så om du behöver returnera lite värde (vilket är valfritt i MS SQL DBMS), måste du uttryckligen förklara en returvariabel i förfarandet.

Vänta på

Vänta för operatören i MS SQL DBMS pausar utförandet ett tag eller före uppkomsten av den angivna tiden. Något som detta kan göras med användardefinierade funktioner (UDFS), i Firebird DBMS. Men i både DBMs bör användningen av en sådan operatör uteslutas, eftersom kundens interaktion är helt suspenderad (i Firebird DBMs, kan den också avbrytas för att avbryta underhållet av alla anslutningar, och inte bara den anslutning som orsakade analogen av Den angivna operatören är ca. transl.).

Standardoperatörer

Standardoperatörer som finns i båda DBMS är markerade, infoga, uppdatering och radering. DBMS Firebird och MS SQL stöder dem, men i MS SQL DBMS finns det flera icke-standardiserade förlängningar av dessa operatörer, som måste beskrivas om de används.

I Firebird DBMS tillåter Select-uttalandet inte användningen av det in i sökordet för att skapa ett nytt bord "på flugan". Istället används i sökordet för att kommunicera resultatet av frågan från variabeln.

/ * MS SQL-syntax för att tilldela det variabla fältvärdet. * / Välj @my_state \u003d state från författare där auth_name \u003d "John" / * Firebird Syntax. * / Välj tillstånd till: Stat / * -\u003e Note ":" Före namnet på variabeln * / från författare där Auth_Name \u003d "John"

I DBMS MS SQL 7 och ovan i SELECT-satsen kan du ange toppspecifikatorn för organisationen av den returnerade dataseten. Den här funktionen är för närvarande under utveckling för Firebird DBMS. (Första och hoppa över specifikationer i Firebird DBMS introduceras, från version 1.5. - Obs.

Både DBMS MS SQL och Firebird stöder den vanliga syntaxen för insatsoperatören och insatsen ..Välj uttalande.

Både DBMS MS SQL och Firebird stöder den vanliga uppdateringsoperatörsyntaxen. MS SQL DBMS stöder också den uppdaterade operatörssyntaxen, där anslutningen utförs (gå med) och uppdaterar ett av anslutningsborden. Du kan tänka på det som om villkoret på steroider. Om en sådan funktion är mycket nödvändig kan den implementeras i Firebird DBM med visning (visningar).

Både DBMS MS SQL och Firebird stöder den vanliga raderingssyntaxen. MS SQL DBMS stöder också avkortningsbordsoperatören, vilket är effektivare (men mer och farligare) än det raderade uttalandet. (MS SQL DBMS stöder också den radera operatörssyntaxen, där anslutningen utförs. - Obs.

/ * MS SQL-syntax för att radera alla my_Table-poster. * / Truncate tabell my_table / * ... eller ... * / ta bort från my_table / * firebird syntax. * / Ta bort från my_table

Använda transaktioner

Firebird DBMS i DSQL (Dynamic SQL) används inte i DSQL. Namngivna transaktioner i det här fallet är inte tillgängliga alls. (DSQL-operatörer exekveras i samband med transaktioner som körs och kontrolleras av klientansökan. - Ref. Transl.) Syntaxen för båda DBMS stöder det sökord för kompatibilitet.

I de flesta fall bör transaktionsproblem inte uppstå: Explicit transaktionshantering "på plats" i MS SQL DBMS används vanligtvis på grund av brist på supportkontroll (undantag).

ledtråd

I DBMS MS SQL finns det en global variabel XACT_ABORT som styr transaktionsrullen när körtidsfelet uppstår (körtidsfel). Annars måste du kontrollera värdet på @@ felvariabeln efter utförandet av varje operatör.

I allmänhet försvinner de flesta problem som är förknippade med nivåerna av transaktionsisolering i MS SQL DBMS när de flyttas till Firebird DBMS. Rivaliteten mellan "läsare" och "författare" är minimalt på grund av användningen av multi-board arkitektur (multigenereringsarkitektur, MGA).

I DBMS används SQL-markörer huvudsakligen för att flytta på förfrågningsresultat för att utföra några steg med dessa resultat. Förutom syntax finns det ingen stor skillnad att utföra samma uppgift. Även om det finns alternativ för att gå framåt och bakåt, används i praktiken, för det mesta, enriktade markörer.

/ * MS SQL-syntax. * / Förklara my_cursor markör för att välja au_lname från declare @au_lname varchar (40) öppna my_cursor hämta nästa från my_cursor till @au_lname medan @@ fetch_status \u003d 0 börja / * göra något intressant med @au_lname. * / Hämta Nästa från My_Cursor End Close My_Cursor DealLocate My_Cursor / * Firebird Syntax. * / Deklarera variabel au_lname varchar (40); ... för att välja au_lname från författare Beställ av au_lname till: au_lname gör börja / * göra något intressant med au_lname. * / Slutet.

Observera att MS SQL DBMS kan placera markörer i variabler och sända dessa variabler som parametrar. Det är omöjligt att firebird DBMS.

Här är en komplett lista med funktioner för att arbeta med rader från BOL:

ASCII. NCHAR. Soundex.
Röding. Patindex. Plats.
Charindex. Byta ut Str.
Skillnad Kvotnamn Grejer
Vänster. Återskapa. Substring
Len. Omvänd Unicode.
Lägre Rätt Övre
Ltrim. Rtrim.

Låt oss börja med två ömsesidigt omvända funktioner - ASCII. och Röding..

ASCII-funktionen returnerar ASCII-koden för den vänstra stränguttryckssymbolen, vilket är funktionens argument.

Här, till exempel, hur man bestämmer hur mycket det finns olika bokstäver från vilka namnen på fartygen börjar i skeppstabellen:


Det bör noteras att ett liknande resultat kan erhållas lättare med en mer funktion - Vänster.som har följande syntax:

Vänster (<stränguttryck>, <heltaluttryck>)

och sänker antalet tecken till det andra argumentet, vilket är det första argumentet som anges av det andra argumentet. Så,

Välj distinkt Vänster (Namn, 1) Från Fartyg Beställa med 1

Men hur kan du till exempel få ett bord med koder för alla alfabetiska tecken:

Välj Char (ASCII ("A") + NUM-1) Brev, ASCII ("A") + NUM - 1
Från (välj 5 * 5 * (A-1) + 5 * (B-1) + C som NUM
Från (Välj 1 A Union All Välj 2 Union All Välj 3 Union All Välj 4 Union All Välj 5) x
Cross gå med.
(Välj 1 B Union All Välj 2 Union All Välj 3 Union All Välj 4 Union All Välj 5) Y
Cross gå med.
(Välj 1 C Union All Välj 2 Union All Välj 3 Union All Välj 4 Union All Välj 5) Z
) X.
Där ASCII ("A") + NUM -1 mellan ASCII ("A") och ASCII ("Z")

De som inte är aktuella med generering av numerisk sekvens, som skickar till lämplig artikel.

Som du vet skiljer sig koder med små bokstäver och stora bokstäver. För att få en komplett uppsättning utan att skriva om en förfrågan är det därför tillräckligt att lägga till ovanstående kod som liknar:


Jag tror att det inte är svårt att lägga till det här brevet till bordet, om det behövs.

Vi överväger nu uppgiften att bestämma sökandet efter önskad substring i stränguttrycket. För detta kan två funktioner användas - Charindex. och Patindex.. Båda returnerar den ursprungliga positionen (positionen för den första substringsymbolen) substring i raden. Charindex-funktionen har syntax:

Charindex ( skeeping_some, string_inpection[, start_position])

Här är en valfri heltalsparameter start_position bestämmer positionen i stränguttrycket, från vilken sökningen utförs önskad) . Om denna parameter utelämnas, utförs sökningen från början string_dasses. Till exempel, fråga

Det bör noteras att om det är , det önskade substratet antingen ett stränguttryck, kommer resultatet också att vara noll.

Följande exempel bestämmer positionerna för den första och andra posten av symbolen "A" i fartygets namn "Kalifornien"

Välj Charindex ("A", namn) first_a,
Charindex ("A", namn, Charindex ("A", namn) +1) Second_a
Från fartyg där namn \u003d "Kalifornien"

Observera att när man bestämmer det andra tecknet används startpositionen i funktionen, vilket är läget för första bokstaven "A" av tecknet - Charindex ("A", namn) +1. Rättigheten av resultatet är 2 och 10 - det är lätt att kontrollera :-).

Patindex-funktionen har syntax:

Patindex ("% prov%" , string_inpection)

Den viktigaste skillnaden i denna funktion från Charindex är att söksträngen kan innehålla jokertecken -% och _. I det här fallet är de terminala tecknen "%" obligatoriska. Till exempel kommer med denna funktion i det första exemplet att vara


Resultatet av denna förfrågan är som följer:


Det faktum att vi som ett resultat kommer att få en tom resulterande uppsättning innebär att det inte finns några sådana skepp i databasen. Låt oss ta en kombination av värden - klassen och fartygets namn.

Anslutningen av två strängvärden i en heter koncatentationoch B. SQL Server För denna operation används "+" -tecknet (i standard "||"). Så,

Och om stränguttrycket innehåller bara ett brev? Förfrågan kommer att leda den. Detta är lätt att se till att skriva

I den första delen har vi redan rört DML-språket, med nästan hela uppsättningen av hans kommandon, med undantag för sammanslagningen.

Jag kommer att berätta om DML av min sekvens utvecklad på personlig erfarenhet. I kursen kommer jag också att försöka berätta om "hala" platser som uppmärksamheten är värt att betona, dessa "hala" platser är liknande i många SQL-dialekter.

Eftersom Textboken är tillägnad en bred cirkel av läsare (inte bara programmerare), förklaringen kommer ibland att vara lämplig, d.v.s. Lång och tråkig. Detta är min vision om ett material som huvudsakligen erhålls i praktiken till följd av yrkesverksamhet.

Huvudsyftet med den här läroboken, steg för steg, för att utarbeta en fullständig förståelse för kärnans språk och undervisa de korrekt använda sina mönster. Professionella i detta område kan också vara intresserade av att rulla detta material, kanske de kommer att kunna göra något nytt för sig själva, eller kanske kommer det helt enkelt att vara användbart att avslöja för att uppdatera minne för ändamål. Jag hoppas att allt kommer att vara intresserat.

Eftersom DML i MS SQL-databasdialekten är mycket starkt förknippad med Select Design-syntaxen, jag börjar prata om DML från den. Enligt min mening är Select Design den viktigaste utformningen av DML-språket, för På grund av det eller dess delar samplas ett prov av nödvändiga data från databasen.

DML-språk innehåller följande konstruktioner:

  • Välj - Dataprovtagning
  • Infoga - Sätt in nya data
  • Uppdatering - Datauppdatering
  • Ta bort - Ta bort data
  • Merge - Data Merge

I den här delen kommer vi att överväga endast den grundläggande syntaxen i Select-kommandot, vilket är följande:

Välj list_stolbtsy eller * från källa där filterorder med expression_sortion
Temat för Select-uttalandet är mycket omfattande, så i den här delen kommer jag att sluta bara på sina grundläggande strukturer. Jag tror att, inte att veta bra basen, kan du inte börja lära dig mer komplexa mönster, för Vidare kommer allt att spinna runt den här grundläggande designen (underskott, associering, etc.).

Också inom den här delen kommer jag också att prata om erbjudandet. Detta erbjudande som jag tänkte indikerade inte i den grundläggande syntaxen, eftersom Det implementeras annorlunda i olika SQL-dialekter.

Om DDL-språket är mer statiskt, d.v.s. Med hjälp av det skapas styva strukturer (tabeller, kommunikation etc.), DML-språket är dynamiskt, här kan du få rätt resultat på olika sätt.

Utbildning kommer också att fortsätta i steg för stegläge, d.v.s. Vid läsning måste du omedelbart försöka utföra exemplet. När du har analyserat resultatet och försök att förstå det intuitivt. Om något förblir oförståeligt, till exempel värdet av någon funktion, kontakta sedan Internet.

Exempel kommer att visas på testdatabasen, som skapades med användning av DDL + DML i den första delen.

För dem som inte har skapat databasen i den första delen (eftersom inte alla kan vara intresserade av DDL-språket), kan använda följande skript:

Test BD Creation Script

Creation Create Database Test Go - Gör Test Test Nuvarande Användning Test GO - Skapa tabeller Directory Skapa tabellpositioner (ID INT Identity (1,1) Inte NULL CONSTAINT PK_POSITIONS Primär nyckel, namn NVARCHAR (30) NOT NULL) Skapa tabellavdelningar (ID INT Identitet (1,1) Not NULL CONSTAINT PK_DEPARTIONS Primärnyckel, namn NVARCHAR (30) NOT NULL) GO - Fyll ut Table Directory Directory Data Ange identitet_insert Positioner på Infoga positioner (ID, Namn) Värden (1, N "Accountant" ), (2, n "regissör"), (3, n "programmerare"), (4, n "senior programmerare") Ange identitet_insert positioner av Go Set Identity_insert Departments On Insert Departments (ID, NAME) Värden (1 , N "Administration"), (2, N "Redovisning"), (3, n "it") Ange identitet_insert avdelningar avgå - Skapa ett bord med Skapa tabell Medarbetare (ID NOLL, NAME NVARCHAR (30), födelsedagsdatum , Email NVARCHAR (30), POSITIONID INT, DepartmentID INT, HANDERAT DATUM INTE NULL CONSTAINT DF_EMPLOYEES_HIRADEATE DEFAULT SYSDATETIDE (), Managerid Int, C Onstraint pk_employees Primärnyckel (ID), Begränsning FK_EMUTEEES_DEPENDEIDID FRAMSKAP (DEBRESSFID) Referenser Avdelningar (ID), Begränsning FK_EMULTEES_POSITIONID UTLANDE KEY (POSITIID) Referenser Positioner (ID), Begränsning FK_EMOLYES_MANAGERID UTLANDE KEY (ManagerID) Referenser Medarbetare (ID), Begränsning UQ_EMLOWEES_EMAIL Unique (E-post), begränsning ck_employees_id check (id mellan 1000 och 1999), index idx_employees_name (name)) gå - fyll den med infoga anställda (ID, namn, födelsedag, email, positionid, departmentID, managerid) värden (1000, n "Ivanov I.i.", "19550219", " [E-post skyddad]", 2,1, null), (1001, n" Petrov PP "," 19831203 "," [E-post skyddad]", 3,3,1003), (1002, N" Sidorov S.S. "," 19760607 "," [E-post skyddad]", 1,2,1000), (1003, n" andreev aa. "," 19820417 "," [E-post skyddad]",4,3,1000)

Allt, nu är vi redo att börja lära sig DML-språket.

Välj - Data provtagningsoperatör

Först och främst, för en aktiv frågasredigerare, kommer vi att göra den aktuella testdatabasen genom att välja den i rullgardinsmenyn eller "Använd test" -kommandot.

Låt oss börja med den elementära valda formuläret:

Välj * från anställda
I den här frågan ber vi dig att återvända alla kolumner (anger "*") från medarbetarbordet - du kan läsa den som "Välj All_noles från Table_StArts." Om du har ett klusterindex, är de returnerade uppgifterna sannolikt sorterat av det, i det här fallet på ID-kolumnen (men det är inte viktigt, eftersom vi i de flesta fall kommer att indikera uttryckligen med ordning med ...):

Id Namn. Födelsedag E-post Positionid. Avdelningen. Hyrdat. Managerid.
1000 Ivanov I.I. 1955-02-19 [E-post skyddad] 2 1 2015-04-08 NULL
1001 Petrov P.P. 1983-12-03 [E-post skyddad] 3 3 2015-04-08 1003
1002 Sidorov S.S. 1976-06-07 [E-post skyddad] 1 2 2015-04-08 1000
1003 Andreev a.a. 1982-04-17 [E-post skyddad] 4 3 2015-04-08 1000

I allmänhet är det värt att säga att i MS SQL-dialekten kan den enkla formen av väljförfrågan inte innehålla från blocket, i det här fallet kan du använda den för att få vissa värden:

Välj 5550/100 * 15, SYSDATETIDE () - Hämta en systemdatabas SIN (0) + COS (0)

Inget kolumnnamn) Inget kolumnnamn) Inget kolumnnamn)
825 2015-04-11 12:12:36.0406743 1

Observera att uttrycket (5550/100 * 15) gav resultatet 825, även om vi anser att räknaren (832,5). Resultatet 825 visade sig av anledningen att alla siffror i vårt uttryck är heltal, därför är resultatet ett heltal, d.v.s. (5550/100) ger oss 55, inte (55,5).

Kom ihåg följande att nästa logik fungerar i MS SQL:

  • Hel / heltal \u003d hel (dvs i det här fallet finns en heltal division)
  • Verklig / hel \u003d verklig
  • Hela / Real \u003d Real
De där. Resultatet omvandlas till en större typ, därför i 2RS, får vi ett reellt tal (anledning som i matematik - intervallet av reella tal är större än omfattningen av heltal, därför omvandlas resultatet till det):

Välj 123/10, - 12 123./10, - 12.3 123/10. - 12,3.
Här (123.) \u003d (123,0), bara i det här fallet 0 kan kasseras och lämna endast en punkt.

Med andra aritmetiska operationer har samma logik samma logik, helt enkelt när det gäller att dividera denna nyans mer relevant.

Var därför uppmärksam på typen av data i numeriska kolumner. I händelse av att det är en helhet, och det resultat du behöver för att bli verklig, använd sedan omvandlingen, eller helt enkelt sätta punkten efter det nummer som anges som en konstant (123.).

För att konvertera fält kan du använda den gjutna eller konvertera funktionen. Vi använder till exempel ID-fältet, det är typ int:

Välj ID, ID / 100, "En heltal division av gjut (ID som flottör) / 100 kommer att inträffa här - använd den gjutna funktionen för att konvertera till flytkonverteringstypen (Float, ID) / 100, - Använd konvertera funktionen för att konvertera att skriva float ID / 100. - Vi använder konvertering genom att ange att nämnaren är det reella numret från anställda

Id Inget kolumnnamn) Inget kolumnnamn) Inget kolumnnamn) Inget kolumnnamn)
1000 10 10 10 10.000000
1001 10 10.01 10.01 10.010000
1002 10 10.02 10.02 10.020000
1003 10 10.03 10.03 10.030000

På en anteckning. I Oracle-databasen är syntaxen utan ett från block oacceptabelt, det finns ett dubbelsystembord för detta ändamål, som innehåller en rad:

Välj 5550/100 * 15 - och i Oracle kommer resultatet att vara 832,5 SYSDATE, SIN (0) + COS (0) från Dual


Notera. Namnet på bordet i många RBD kan föregås av systemnamnet:

Välj * Från dbo.employees - DBO - Scheme Namn

Schemat är en logisk enhet i databasen som har sitt eget namn och låter oss gruppera databasobjekt som tabeller, vyer etc.

Schema-definitionen i olika databaser kan skilja sig, någonstans är diagrammet direkt relaterat till databasanvändaren, dvs. I det här fallet kan det sägas att systemet och användaren är synonymer och alla föremål som skapas i schemat är väsentligen föremål för den här användaren. I MS SQL är systemet en oberoende logisk enhet som kan skapas av sig själv (se Skapa schema).

Som standard, i MS SQL-databasen, skapas ett schema med DBO-namnet (databasinnehavare) och alla standardobjekt skapas i detta schema. Följaktligen, om vi anger tabellnamnet i frågan, kommer det att undertecknas i DBO-kretsen i den aktuella databasen. Om vi \u200b\u200bvill skapa ett objekt i ett specifikt system måste vi också förhindra ordningsnamnet för systemet med namnet på systemet, till exempel "Skapa Table_Shemi.

I fallet med MS SQL kan schemanamnet fortfarande föregås av databasens namn, där detta system är beläget:

Välj * från test.dbo.mployees - namnbas. Ishim.tablik
Sådan förtydligande är till exempel användbar, om:

  • i en begäran vädjar vi till föremål som ligger i olika kretsar eller databaser.
  • det är nödvändigt att göra dataöverföring från en krets eller databas till en annan
  • att vara i en databas måste du begära data från en annan databas
  • etc.
Schemat är ett mycket bekvämt verktyg som är användbart att använda när du utvecklar BD-arkitekturen, och särskilt stora databaser.

Vi glömmer inte heller att i texten på den begäran kan vi använda som enstaka "- ..." och multi-line "/ * ... * /" Kommentarer. Om förfrågan är stor och komplicerad kan kommentarer hjälpa dig, eller någon annan, efter en tid, kom ihåg eller förstå dess struktur.

Om kolumnerna i tabellen är mycket, och speciellt om det fortfarande finns många strängar i tabellen, plus till om vi gör förfrågningar till databasen i nätverket, är provet att föredra för den direkta noteringen av fälten Du behöver via kommatecken:

Välj ID, namn från anställda

De där. Här säger vi att vi bara måste returnera ID och namnfält från bordet. Resultatet kommer att vara följande (förresten som Optimizer här bestämde dig för att använda det index som skapades med namnfältet):

Id Namn.
1003 Andreev a.a.
1000 Ivanov I.I.
1001 Petrov P.P.
1002 Sidorov S.S.

På en anteckning. Ibland är det användbart att titta på hur data samplas, till exempel, för att ta reda på vilka index som används. Detta kan göras om du trycker på "Display Estimated Execution Plan - visa den beräknade planen" eller installera "inkluderar faktisk exekveringsplan - för att inkludera den aktuella förfrågningsplanen för frågan" (i det här fallet kan vi se den verkliga planen respektive , först efter utförandet av frågan):

En analys av exekveringsplanen är mycket användbar när du optimerar frågan, det gör det möjligt för dig att ta reda på vilka index som saknas eller vilka index som inte används alls och kan raderas.

Om du just börjat behärska DML, nu är det inte så viktigt för dig, bara ta en anteckning och du kan säkert glömma det (kanske det kommer aldrig att vara bra för dig) - Vårt första mål är att studera grunden för DML-språket Och lär dig hur du applicerar dem korrekt, och optimering är redan separat konst. Ibland är det viktigare att i händerna bara en korrekt skriftlig förfrågan, som returnerar det korrekta resultatet ur ämnesynpunkt, och enskilda personer är redan engagerade i optimering. Först måste du lära dig hur du skriver rätt att skriva förfrågningar med hjälp av vilket som helst för att uppnå målet. Det huvudsakliga målet du bör uppnå - din förfrågan returnerar rätt resultat.

Ställa in aliaser för tabeller

När du lovar högtalarna kan de förbereda bordsnamnet i det från blocket:

Välj anställda.id, anställda. Namn från anställda

Men en sådan syntax är vanligtvis obekväma, för Bordnamnet kan vara länge. För dessa ändamål är kortare namn frågade - Alias \u200b\u200b(alias):

Välj emp.id, emp.name från anställda som emp
eller

Välj EMP.ID, EMP.NAME från anställda EMP - som nyckelord kan släppas (jag föredrar ett sådant alternativ)

Här är EMP en pseudonym för de anställdas tabell, som kan användas i samband med detta valda uttalande. De där. Vi kan säga att i samband med detta väljer uttalande anger vi ett nytt namntabell.

Naturligtvis, i det här fallet, kommer resultaten av förfrågningarna att vara exakt detsamma som för "Välj ID, namn från anställda". För vilket det måste vara tydligt (inte ens i den här delen), samtidigt som du bara kommer ihåg att kolumnens namn kan förberedas (förtydligande) eller direkt tabellnamnet eller med hjälp av en pseudonym. Här kan du använda en av två, d.v.s. Om du ställer in en pseudonym, måste du använda den, och det är omöjligt att använda tabellnamnet.

På en anteckning. I Oracle säger vi bara en version av bordet Alias \u200b\u200bav ett bord utan ett nyckelord som.

DISTINCT - Duplicera radringar

Det distinkta sökordet används för att kassera dubbla radförfrågan från resultatet. Ung talande, föreställ dig att frågan först exekveras utan det distinkta alternativet, och sedan utesluts alla dubbletter från resultatet. Vi kommer att visa detta för större synlighet på exemplet:

Skapa ett tillfälligt bord Skapa tabell #Trash (ID int inte null Primärnyckel, Col1 Varchar (10), Col2 Varchar (10), Col3 Varchar (10)) - Fyll i tabellen genom Infoga #Trash (ID, COL1, COL2, COL3 ) värden (1, "a", "a", "a"), (2, "a", "b", "c"), (3, "c", "a", "b" ), (4, "a", "a", "b"), (5, "b", "b", "b"), (6, "a", "a", "b"), (7, "a", "a", "a"), (8, "c", "a", "b"), (9, "c", "a", "b"), (10 , "A", "A", "B"), (11, "a", , "b"), (12, "a", , "b") - låt oss se vad som returnerar en förfrågan utan Alternativ DISTINCT SELECT COL1, COL2, COL3 från #TRASH - Se vad som returnerar en fråga med den distinkt Välj distinkt Col1, Col2, Col3 från #Trash-alternativ - Ta bort droppbordet #trash tillfälligt bord

Det kommer tydligt att se ut så här (alla dubbletter är markerade med en färg):

Låt oss nu titta på var det kan tillämpas på ett mer praktiskt exempel - bara de unika identifierarna av avdelningarna från de anställdas tabell (dvs. Vi lär oss av ID för de avdelningar där anställda är listade):

Välj distinkt avdelningsid från anställda

Här fick vi 4 linjer, för Upprepande kombinationer (avdelningenID, positionID) i vårt bord där.

Strax tillbaka till DDL

Eftersom data för demonstrationsexempel börjar saknas, och jag vill berätta mer omfattande och förståeligt, låt oss expandera vårt anställningsbord. Dessutom är en liten återkallelse DDL, som de säger, "repetition är undervisningsmammen", och plus lite senare kommer att störa några och tillämpa uppdateringsoperatören:

Skapa nya högtalare Alter Table Anställda Lägg till nednamn NVARCHAR (30), - efternamnet förnamn Nvarchar (30), - Namnet Middlename Nvarchar (30), - Lönens flottörs patronymic - Procentandelen för att beräkna bonusen från lönlönen - fyll i med sina data (vissa data avser att missa) Uppdatera anställda Set LastName \u003d N "Ivanov", förnamn \u003d N "Ivan", Middlename \u003d N "Ivanovich", Lön \u003d 5000 , BonusPercent \u003d 50 där ID \u003d 1000 - Ivanov I.i. Uppdatera anställda Set LastName \u003d N "Petrov", Förnamn \u003d N "Peter", Middlename \u003d N "Petrovich", Lön \u003d 1500, Bonusepercent \u003d 15 Var ID \u003d 1001 - Petrov P.P. Uppdatera anställda set nednamn \u003d n "sidor", förnamn \u003d n "sidor", middlename \u003d , lön \u003d 2500, bonuspercent \u003d null där id \u003d 1002 - Sidorov S.S. Uppdatera anställda Set LastName \u003d N "Andreyev", förnamn \u003d n "Andrey", Middlename \u003d Null, Lön \u003d 2000, BonusePercent \u003d 30 Var ID \u003d 1003 - Andreev A.A.

Se till att data uppdaterades framgångsrikt:

Välj * från anställda

Id Namn. Efternamn. Förnamn. Mellannamn. Lön. Bonusepercent.
1000 Ivanov I.I. Ivan Ivan. Ivanovich 5000 50
1001 Petrov P.P. Petrov Peter Petrovich 1500 15
1002 Sidorov S.S. Sidorov Sidor. NULL 2500 NULL
1003 Andreev a.a. Andreev Andrei NULL 2000 30

Ställa in aliaser för Query-kolumner

Jag tycker att det blir lättare att visa vad du ska skriva:

Välj - Ange namnet till den beräknade kolumnen nednamn + "" + förnamn + "" + Middlename som fullständigt namn, - med hjälp av dubbla citat, eftersom Hyredatet som utrymme "datum" används, - användningen av kvadratkonsoler, eftersom Födelsedag som [födelsedatum] används - Ordet som inte nödvändigtvis löne ZP från anställda

Fullständiga namn kvittots datum Födelsedatum Z P.
Ivanov Ivan Ivanovich 2015-04-08 1955-02-19 5000
Petrov Petrov 2015-04-08 1983-12-03 1500
NULL 2015-04-08 1976-06-07 2500
NULL 2015-04-08 1982-04-17 2000

Eftersom vi ser kolumnerna pseudonymer som ges av oss, återspeglas i rubriken för det resulterande tabellen. Egentligen är detta huvudsyftet med pseudonymer av kolumner.

Anteckna det De senaste 2 anställda är inte angivna av patronymic (nollvärde), resultatet av uttrycket "LastName +" "+ FirstName +" "+ Middlename" återvände också till oss null.

För anslutning (addition, concatenation) strängar i MS SQL används "+" -symbolen.

Vi kommer ihåg att alla uttryck där null deltar (till exempel divisionen på , tillägg med null) kommer att återvända null.

På en anteckning.
I fallet med Oracle används operatören "||" "för att kombinera strängar Och sammanfattningen kommer att se ut som "LastName ||" "|| förnamn ||" "|| Middlename." För Oracle är det värt att notera att det har ett undantag för strängtyper, för dem null och en tom linje "" Det här är samma sak, så i Oracle, kommer ett sådant uttryck att återvända för de senaste 2 anställda i Sidor Sidor och Andrei . Vid tidpunkten för den version av Oracle 12c, så vitt jag vet, är alternativen som ändras detta beteende inte (om inte rätt, snälla korrigera mig). Det är svårt för mig att döma väl eller dåligt, för I vissa fall är det bekvämare än nollsträngens beteende som i MS SQL, och i andra som i Oracle.

Oracle är också tillåtet av alla listade pseudonymer av kolumner, förutom [...].


För att inte göra en design med ISNull-funktionen, kan vi i MS SQL applicera Concat-funktionen. Tänk på och jämför 3 alternativ:

Välj efternamn + "" + FirstName + "" + Middlename FullName1, - 2 Alternativ för att byta null tomma strängar "" (vi får beteende som i Oracle) Isnull (LastName, "") + "" + Isnull (FirstName, "") + "" + Isnull (Middlename, "") fullnamn2, Concat (LastName, ", förnamn," ", middlename) fullname3 från anställda

Fullnamn1 Fullnamn2. Fullnamn3.
Ivanov Ivan Ivanovich Ivanov Ivan Ivanovich Ivanov Ivan Ivanovich
Petrov Petrov Petrov Petrov Petrov Petrov
NULL Sidor sidorov Sidor sidorov
NULL Andreyev andrey Andreyev andrey

I MS SQL kan pseudonymer fortfarande ställas till att använda jämställdhetsskylten:

Välj "Datum för mottagning" \u003d Hyrdat, - Förutom "..." och [...] kan användas "..." [Födelsedag] \u003d Födelsedag, ZP \u003d Lön från anställda

Använd för att ställa in ett pseudonym sökord som eller lika tecken, förmodligen mer smak. Men när det gäller andra förfrågningar kan dessa kunskaper vara användbara.

Slutligen kommer jag att säga att för alias är namnen bättre att ställa in, med endast latinska tecken och siffror, undviker användningen av "...", "..." och [...], det vill säga använd samma regler som vi använde med namnet på tabellerna. Vidare, i exemplen kommer jag bara att använda sådana namn och nej "...", "..." och [...].

Main Arithmetic SQL-operatörer


Prioriteten för att utföra aritmetiska operatörer är densamma som i matematik. Om det behövs kan proceduren för användning av operatörer ändras med hjälp av runda fästen - (A + B) * (X / (Y-Z)).

Och återigen upprepar jag att någon operation med null ger , till exempel: 10 + , null * 15/3, 100 / null - allt detta kommer att ge som ett resultat av null. De där. Att tala helt enkelt obestämt värde kan inte ge ett visst resultat. Tänk på detta när du skapar en fråga och, om nödvändigt, bearbeta nollvärden Funktioner Is, Coalesce:

Välj ID, namn, lön / 100 * BONUSSPERCENT AS Resultat1 - utan nollbehandlingslön / 100 * Isnull-värden (Bonuspercent, 0) som resultat2, - Använd funktionen Isnull Lön / 100 * Coalesce (BonusPercent, 0) som resultat3 - - Använd Coalesce från anställdas funktion

Jag ska berätta lite om Coalesce-funktionen:

Coalesce (Expr1, Expr2, ..., Exprn) - Returnerar det första icke-nullvärdet från listan över värden.

Välj Coalesce (F1, F1 * F2, F2 * F3) Val - I det här fallet kommer det tredje värdet från (välj null F1, 2 F2, 3 F3) q att återvända

I grund och botten fokuserar jag på historien om DML-språkdesignerna och för det mesta kommer jag inte att prata om de funktioner som finns i exemplen. Om det inte är klart för dig, vilket gör en eller annan funktion. Leta efter sin beskrivning på Internet, du kan även söka efter information omedelbart av grupp av funktioner, till exempel, frågade i sökandet efter Google "MS SQL-strängfunktioner" , "MS SQL-matematiska funktioner" eller "MS SQL-funktioner" nollbehandling. Det finns mycket information om funktioner, och du kan enkelt hitta den. Till exempel, i MSDN-biblioteket, kan du lära dig mer om Coalesce-funktionen:

Skärning från MSDN. Coalesce och fall jämförelse

Coalesce-uttryck är en syntaxmärke för falluttryck. Det betyder att Coalesce Code (Expression1, ... n) skrivs om av Query Optimizer som följande falluttryck:

Fall när (expression1 är inte null) sedan expression1 när (expression2 inte är null) sedan expression2 ... annars expressionsänd

Tänk till exempel hur du kan använda resten från Division (%). Denna operatör är mycket användbar när du behöver dela upp poster i grupper. Till exempel, med alla anställda som har till och med tablettnummer (ID), d.v.s. De ID som är uppdelade i 2:

Välj ID, namn från anställda där ID% 2 \u003d 0 - Återstoden av division med 2 är 0

Beställ By - Query Results Sortera

Beställ BA-erbjudandet används för att sortera sökresultatet.

Välj efternamn, förnamn, lön från anställda Beställ efternamn, förnamn - Sortera resultatet på 2: a kolumner - efter efternamn och efter namn

För anteckning. För att sortera stigande, det finns ett nyckelord ASC, men eftersom sorteringsstigning används som standard, kan du glömma det här alternativet (jag kommer inte ihåg fallet så att jag en gång använt det här alternativet).

Det är värt att notera att i den utbud som erbjuds kan du använda de fält som inte är listade i Select-klausulen (förutom när det är distinkt används, kommer jag att berätta om det här fallet nedan). Till exempel, kör lite framåt med det bästa alternativet och visa, till exempel, du kan välja 3 anställda som har högsta sn, med hänsyn till att ZP själv för konfidentialitet inte ska visa:

Välj Top 3 - returnera endast 3 första poster från hela resultatet ID, efternamn, förnamn från anställda Beställning från Lön Desc - Vi assorterar resultatet Descending Löne

Id Efternamn. Förnamn.
1000 Ivan Ivan.
1002 Sidorov Sidor.

Naturligtvis finns det ett fall som flera anställda kan ha samma SN och det är svårt att säga att det är att säga att denna begäran kommer att returnera denna begäran, det är redan nödvändigt att lösa med den ledande uppgiften. Antag, efter diskussion med direktören för den här uppgiften, godkände du och bestämde dig för att använda följande alternativ - göra en extra sortering på fältet för födelsedatum (dvs. de unga har ett unga sätt), och om datumet för Födelse, flera anställda kan sammanfalla (trots allt uteslutet), då kan du göra en tredje sortering som faller ned värdens värden (minst order för provet de kommer att falla de som har en maximal - till exempel de som har antagits av den senare kommer att erkänna tablettnumren från oss successivt):

Välj Top 3 - returnera endast 3 första poster från hela resultatet ID, efternamn, förnamn från anställda Beställning av Lön Desc - 1. Vi sorterar resultatet i fallande orderfödelsedag, - 2. Då efter datum för födelse-ID DESC-3. Och För fullständig definition av resultatet, lägg till sortering efter ID

De där. Du måste försöka vara resultatet av begäran att vara förutsägbar så att du kan förklara vid analysering av flygen varför dessa människor kom in i den svarta listan, d.v.s. Allt valdes ärligt, enligt de godkända reglerna.

Du kan sortera samma med olika uttryck i ordning med så:

Välj efternamn, förnamn från anställda Beställ av Concat (LastName, "", förnamn) - Vi använder uttryck

Även i ordning kan du använda alias som är inställda för kolumner:

Välj Concat (LastName, "", förnamn) FI från anställda Beställning av FI - Vi använder Alias

Det är värt att notera att i fallet med att använda det tydliga förslaget kan endast de kolumner som anges i Select-blocket användas i ordern. De där. Efter att ha tillämpat den distinkta operationen får vi en ny uppsättning data, med en ny uppsättning kolumner. Av denna anledning kommer följande exempel inte att fungera:

Välj DISTINCT LASTNAME, FIRSTNAME, LÖN FRÅN ANSTÄLLDA BESTÄLLNING AV ID - ID saknas i den slutliga uppsättningen som vi har använt

De där. Beställ BA-erbjudandet är redan tillämpat på den slutliga uppsättningen, innan du utfärdar resultatet till användaren.

Anteckning 1. Också i beställningen kan du använda antalet kolumner som anges i Välj:

Välj efternamn, förnamn, lön från anställda Beställ by - Sortera i ordning 3 desc - 1. Löne minskar 1, - 2. Efter efternamn 2 - 3. Med namn

För nybörjare ser det bekvämt ut och frestande, men det är bättre att glömma och aldrig använda det här sorteringsalternativet.

Om i det här fallet (när fälten är klart), är det här alternativet till och med tillåtet, då för fallet med "*" är ett sådant alternativ bättre aldrig att appliceras. Varför - för om någon till exempel kommer att ändra kolumnernas ordning i tabellen, eller kolumnerna kommer att radera (och det här är en normal situation), kan din förfrågan också fungera, men det är inte fel, för Sortering kan redan gå igenom andra kolumner, och det är täckt av det faktum att det här felet kan upptäckas mycket snart.

I händelse av att inläggen var klart listade, då i ovanstående situation, begäran eller skulle fortsätta att arbeta, men också korrekt (eftersom allt är klart definierat), eller det skulle helt enkelt ge ett fel att den här kolumnen inte existerar.

Så du kan säkert glömma sortering enligt antalet kolumner.

Anteckning 2.
I MS SQL, med en sorteringsstigning, , kommer värdena att visas först.

Välj BonusePercent från anställda Beställ BonusePercent

Följaktligen, när de använder Desc, kommer de att vara i slutet

Välj BonusePercent från anställdas order via BonusPercent Desc

Om du behöver ändra logiken för att sortera nollvärden, använd uttryck, till exempel:

Välj BonusePercent från anställdas order av Isnull (BonusePercent, 100)

Oracle för detta ändamål, 2 alternativ nulls först och null sist tillhandahålls (tillämpas som standard). Till exempel:

Välj BonusePercent från anställda Beställ BonusePercent Desc Nulls sist

Var uppmärksam på detta när du byter till en eller annan databas.

Top - returnera det angivna antalet poster

Klipp från MSDN. Topp - begränsar antalet rader som returneras i den resulterande frågan till ett angivet antal eller procentuellt värde. Om det övre erbjudandet används i samband med ordningen genom förslag är den resulterande uppsättningen begränsad till de första nsträngarna i det sorterade resultatet. Annars returneras de första n-strängarna på obestämd tid.

Typiskt används detta uttryck med ordning med förslag och vi har redan tittat på exempel när det var nödvändigt att returnera n första rader från den resulterande uppsättningen.

Utan ordning i detta förslag används när du bara behöver titta på bordet okänt för oss, där det kan finnas många poster, i det här fallet kan vi till exempel be oss att återvända till oss bara de första 10 Linjer, men för tydlighet kommer vi bara att säga 2:

Välj Top 2 * från anställda

Du kan också ange ordet procent, för att returneras till procentandelen rader från resultatuppsättningen:

Välj Topp 25 procent * från anställda

I min övning används urvalet för antalet linjer.

Också med toppen kan du använda alternativet med slipsar, vilket hjälper till att returnera alla rader i händelse av tvetydig sortering, dvs. Detta förslag kommer att returnera alla linjer som är lika i sammansättningen av raderna som faller i det övre n-provet, som ett resultat av raderna kan väljas mer än N. Låt oss lägga till en annan "programmerare" med lön 1500:

Infoga anställda (ID, Namn, Email, Positionid, DepartmentID, ManagerID, Lön) Värden (1004, N "Nikolaev N.N.", " [E-post skyddad]",3,3,1003,1500)

Och vi introducerar en annan anställd utan att specificera posten och avdelningen med lön 2000:

Infoga anställda (ID, Namn, E-post, Positionid, DepartmentID, ManagerID, Lön) Värden (1005, N "Aleksandrov A.A.", " [E-post skyddad]", Null, , 1000,2000)

Låt oss nu välja med hjälp av Ties-alternativet, vilken lön sammanfaller med 3 anställdas lön, med den minsta lönen (jag hoppas vidare kommer det att vara klart vad jag klonar):

Välj Top 3 med slipsar ID, namn, lön från anställdas order av lön

Även om topp 3 är angivet här, men begäran returnerade 4 poster, eftersom Värdet av lön som återvände Topp 3 (1500 och 2000) var i 4 anställda. Det fungerar ungefär som följer:

På en anteckning.
I olika toppdatabasen implementeras det på olika sätt, i MySQL för detta finns det ett gränserbjudande, där du dessutom kan ställa in en första förskjutning.

I Oracle 12c kom också in i deras analoga kombinationsfunktionalitetstopp och gräns - leta efter "Oracle Offset Hämtning". Före version 12c användes vanligtvis pseudo-stråle rownum för detta ändamål.


Och vad kommer det att hända om du tillämpar de distinkta och bästa förslagen samtidigt? Att svara på sådana frågor, genomföra experiment. I allmänhet, var inte rädd och inte vara lat för att experimentera, för Mest missbrukare att träna. Ordningen av ord i select-uttalandet är nästa, den första är distinkt, och efter det kommer till toppen, dvs. Om du argumenterar logiskt och läser från vänster till höger, kommer den första dubbletter att gälla, och sedan kommer toppen att göras på den här uppsättningen. Låt oss kolla och se till att det är:

Välj distinkt topp 2 lön från anställdas order av lön

Lön.
1500
2000

De där. Som ett resultat fick vi 2 den minsta lönen för alla. Naturligtvis kan det finnas ett fall som SN för vissa anställda kanske inte anges (null), eftersom Systemet tillåter oss att. Därför, beroende på uppgiften, gör vi en lösning för att antingen bearbeta nollvärden i storleksordningen, eller helt enkelt kasta bort alla poster som lönen är lika med , och för detta vänder vi oss till studien av det erbjudande.

Var - strängprovstillstånd

Detta erbjudande används för att filtrera poster på ett visst tillstånd. Välj till exempel alla anställda som arbetar i "IT" -avdelningen (dess ID \u003d 3):

Välj ID, efternamn, förnamn, lön från anställda där avdelningenid \u003d 3 - det beställer efternamn, förnamn

Id Efternamn. Förnamn. Lön.
1004 NULL NULL 1500
1003 Andreev Andrei 2000
1001 Petrov Peter 1500

Där erbjudandet är skrivet till beställning genom kommando.

Förfarandet för att tillämpa kommandon till källsatsen av anställda är som följer:

  1. Var - om det anges, är det första från hela uppsättningen anställda endast utvalda genom att uppfylla posten
  2. DISTINCT - Om det anges, kasseras alla dubbletter
  3. Beställ by - Om det anges, är resultatet gjort
  4. Top - Om det anges, returneras endast det angivna antalet poster från det sorterade resultatet.

Tänk på tydlighetsexempel:

Välj distinkt topp 1 lön från anställda där avdelningenID \u003d 3 order av lön

Det kommer tydligt att se ut så här:

Det är värt att notera att null check görs inte ett tecken på jämlikhet, men med hjälp av är null och är inte null operatörer. Kom bara ihåg att på null med hjälp av "\u003d" operatören (jämställdhetsskylt) kan inte jämföras, eftersom Resultatet av uttrycket kommer också att vara noll.

Välj till exempel alla anställda som inte anger avdelningen (dvs avdelningen är null):

Välj ID, namn från anställda där avdelningenID är null

Nu anser vi till exempel bonusen för alla anställda som indikeras av det bonuspervärde (dvs bonuspercent är inte null):

Välj ID, namn, lön / 100 * Bonusuppkomst som bonuspercent är inte null från anställda

Ja, förresten, om du tror, \u200b\u200bkan värdet på bonuspercenten vara lika med noll (0), liksom värdet kan göras med ett minustecken, eftersom vi inte inneburit några begränsningar på detta område.

Tja, berättade om problemet, vi har hittills fått veta att om (bonuspercent<=0 или BonusPercent IS NULL), то это означает что у сотрудника так же нет бонуса. Для начала, как нам сказали, так и сделаем, реализуем это при помощи логического оператора OR и NOT:

Välj ID, namn, lön / 100 * Bonusuppkomst som bonus från anställda där inte (bonuspercent<=0 OR BonusPercent IS NULL)

De där. Här började vi studera booleska operatörer. Uttryck i parenteser "(Bonusepercent<=0 OR BonusPercent IS NULL)» проверяет на то что у сотрудника нет бонуса, а NOT инвертирует это значение, т.е. говорит «верни всех сотрудников которые не сотрудники у которых нет бонуса».

Det här uttrycket kan också omskrivas och omedelbart säga omedelbart "vernelize alla anställda som har en bonus" som uttrycker detta uttryck (bonuspercent\u003e 0 och bonuspercent är inte null):

Välj ID, namn, lön / 100 * Bonusepercent som BonusPercent\u003e 0 och BonusePercent är inte null

Också i det var blockerar, kan du kontrollera olika typer av uttryck med hjälp av aritmetiska operatörer och funktioner. Till exempel kan liknande verifiering göras med hjälp av ett uttryck med en isnull-funktion:

Välj ID, namn, lön / 100 * Bonusuppkomst som bonus från anställda där isnull (bonuspercent, 0)\u003e 0

Boolska operatörer och enkla jämförelsesoperatörer

Ja, ingen matematik här kan inte göra, så vi kommer att göra en liten utflykt på booleska och enkla jämförelsesoperatörer.

Boolean operatörer i SQL-språk Totalt 3 - och eller inte:

För varje booleska operatör kan du citera sanningsborden där det dessutom visas vad resultatet blir när förhållandena kan vara lika med noll:

Det finns följande enkla jämförelsesoperatörer som används för att bilda villkor:

Plus det finns 2 operatörer för att kontrollera värdet / uttrycket på null:

ÄR INGET Kontrollera efter nollkänsla
Är inte noll Kontrollera om ojämlikhet

Prioritet: 1) Alla jämförelsesoperatörer; 2) inte; 3) och; 4) Or.

Vid konstruktion av komplexa logiska uttryck används runda fästen:

((villkor1 och villkor2) eller ej (villkor3 och villkor4 och villkor5)) eller (...)

Också med hjälp av runda parentes kan du ändra standardsekvensen av beräkningar.

Här försökte jag ge en uppfattning om en booleska algebra i tillräcklig volym för arbete. Som du kan se för att skriva förutsättningarna mer komplicerade utan logik gör det inte längre, men det är lite här (och eller inte) och uppfann sitt folk, så allt är ganska logiskt.

Vi går till slutförandet av den andra delen

Eftersom du även kan prata om den grundläggande syntaxen för den valda operatören, kan du prata väldigt länge, men för att hålla sig inom ramen för artikeln, slutligen visar jag ytterligare logiska operatörer - mellan, i och liknande.

Mellan - verifiering av posten i intervallet

Checked_date mellan Initial_ Value and Final_ Value

Ett uttryck kan fungera som värden.

Vi kommer att undersöka på exemplet:

Välj ID, namn, lön från anställda där lön mellan 2000 och 3000 - Vem sp i intervallet 2000-3000

Egentligen mellan är en förenklad bild av formuläret:

Välj ID, namn, lön från anställningar där lön\u003e \u003d 2000 och lön<=3000 -- все у кого ЗП в диапозоне 2000-3000

Innan ordet mellan, kan ordet inte användas, vilket kommer att kontrollera värdet för att inte ange det angivna området:

Välj ID, namn, lön från anställda där lön inte mellan 2000 och 3000 - liknar inte uttryck (lön\u003e \u003d 2000 och lön<=3000)

Följaktligen kan du också kombinera dem med andra förhållanden med hjälp av och eller:

Välj ID, namnslön från anställda där lön mellan 2000 och 3000 - som har ZP i intervallet 2000-3000 och avdelningenID \u003d 3 - att ta hänsyn till endast anställda

Incheckning på listan över värden

Denna operatör har följande formulär:

Checked_ in (value1, value2, ...)

Jag tycker att det är lättare att visa på exemplet:

Välj ID, namn, lön från anställda där positionen i (3.4) - vem har 3 eller 4 inlägg

De där. I huvudsak liknar det följande uttryck:

Välj ID, namn, lön från anställda där positionid \u003d 3 eller positionid \u003d 4 - vem har en position lika med 3 eller 4

I fallet med inte kommer det att vara på samma sätt (vi kommer att få någon annan än de från avdelningen 3 och 4):

Välj ID, namn, lön från anställda där positionid inte i (3.4) - liknar uttryck ej (positionid \u003d 3 eller positionid \u003d 4)

Dessutom kan begäran från INTE i uttryckas genom och:

Välj ID, namn, lön från anställda där positionen<>3 och position<>4 - Ekvivalent positionsid inte i (3,4)

Observera att sökning av nollvärden med i strukturen i det inte fungerar, eftersom Kontrollera null \u003d null kommer att returnera samma , inte sant:

Välj ID, namn, avdelningenid från anställda där avdelningenID i (1.2, null) - null-poster kommer inte att gå in i resultatet

I det här fallet, bryta kontrollen under flera villkor:

Välj ID, namn, avdelningenid från anställda där avdelningenID i (1,2) - 1 eller 2 eller avdelningen är null - eller null

Eller du kan skriva något som:

Välj ID, namn, avdelningen från anställda där isnull (departmentID, -1) i (1,2, -1) - om du är säker på att det inte finns någon avdelning med ID \u003d -1

Jag tror det första alternativet, i det här fallet blir det mer korrekt och pålitligt. Tja, det är bara ett exempel, för att visa vilka andra mönster som kan byggas.

Det är också värt att nämna ett ännu mer snyggt fel i samband med , vilket kan tillåtas när du använder det inte i designen. Låt oss till exempel försöka välja alla anställda, förutom de där avdelningen är 1 eller där avdelningen inte är specificerad alls, dvs. lika med null. Som en lösning föreslås alternativet:

Välj ID, namn, avdelningen från anställda där avdelningen inte i (1, null)

Men genom att slutföra begäran kommer vi inte att få någon sträng, även om vi förväntade oss att se följande:

Återigen spelade skämtet här noll angivet i listan över värden.

Vi kommer att analysera varför i det här fallet ett logiskt fel inträffade. Sprid begäran med och:

Välj ID, namn, avdelningen från anställda där avdelningenID<>1 och avdelningen<>Null - ett problem på grund av denna kontroll på null - detta tillstånd kommer alltid att återvända noll

Rätt villkor (avdelningenID<>Null) Vi ger alltid osäkerhet här, d.v.s. NULL. Låt oss nu komma ihåg sanningsbordet för operatören och, där (sant och null) ger null. De där. När du utför det vänstra villkoret (avdelningen<>1) På grund av ett obestämd rätt tillstånd, som ett resultat, erhåller vi det obestämda värdet av hela uttrycket (avdelningenID<>1 och avdelningen<>Null), så strängen går inte in i resultatet.

För att skriva om villkoret är korrekt enligt följande:

Välj ID, namn, avdelningen från anställda där avdelningen inte i (1) - eller i det här fallet, bara avdelningen<>1 och avdelningenid är inte null - och kontrollera separat inte null

I fortfarande kan du använda med underskott, men vi kommer tillbaka till den formen, redan i de efterföljande delarna av denna lärobok.

Gilla - Kontrollera sträng med mall

Jag kommer bara att berätta om den här operatören i den enklaste formen, som är standard och stöds av de flesta SQL-dialekter. Även i detta formulär kan du lösa många uppgifter som kräver att du kontrollerar innehållet i linjen.

Denna operatör har följande formulär:

Checked_stock som string_sablon

Följande specialtecken kan appliceras i "strängen":

  1. Betoningsskylt "_" - säger att någon enda symbol kan stå i sin plats
  2. Procentandelskylten "%" - säger att på plats kan stå så många tecken, inklusive inte en
Tänk exempel på symbolen "%" (i praktiken, förresten, det är oftare tillämpat):

Välj ID, namn från anställda där namn som "PET%" - som har namnet börjar med bokstäverna "PET" Välj ID, efternamn från anställda där efternamn som "% OV" - Vem har ett efternamn på "s Välj ID" Efternamn från anställda där efternamn som "% re%" - som har ett efternamn innehåller en kombination av "re"

Tänk på exempel med symbolen "_":

Välj ID, efternamn från anställda där efternamn som "_etrov" - som har ett efternamn som består av någon första tecken och efterföljande bokstäver "Etra" Välj ID, efternamn från anställda där efternamnet "____V" - som har ett efternamn består av fyra tecken och efterföljande bokstäver "s"

Med hjälp av Escape kan du ange ett avbrytande tecken som avbryter kontrolleffekten av specialtecken "_" och "%". Detta erbjudande används när du direkt måste kontrollera närvaron av ett procentmärke eller understrykning.

För att demonstrera flykt, låt oss ta soporna i en post:

Uppdatera anställda set firstName \u003d "This_morus innehållande%" där id \u003d 1005

Och låt oss se vad följande förfrågningar kommer att returneras:

Välj * från anställda där förnamn som "%! %%" Escape "!" - Strängen innehåller en "%" Välj * från anställda där förnamn som "%! _%" Escape "!" - Strängen innehåller "_" -tecknet

Om du behöver kolla strängen på hela matchen, är det istället för att det är bättre att använda "\u003d" -tecknet:

Välj * från anställda där förnamn \u003d "Peter"

På en anteckning.
I MS SQL kan den liknande operatörsmallen också fråga en sökning med regelbundna uttryck, läs om det på Internet, om du inte är tillräckligt med standardfunktioner hos den här operatören.

I Oracle för att söka efter reguljära uttryck gäller den regexp_like-funktionen.

Lite om rader

I fallet med att kontrollera strängen för närvaro av Unicode-tecken måste du sätta N-symbolen före citat, d.v.s. N "...". Men eftersom vi har i tabellen alla de symboliska fälten i Unicode-format (Typ Nvarchar), sedan för dessa fält kan du alltid använda ett sådant format. Exempel:

Välj ID, namn från anställda där namn n "PET%" Välj ID, efternamn från anställda där nednamn \u003d n "PetTro"

Om du gör det korrekt, när du jämför med ett VARCHAR-typfält (ASCII), försöker använda kontroller med "...", och när du jämför fältet med typen NVarchar-typ måste du försöka använda kontroller med n ". .. ". Detta görs för att undvika i färd med att utföra begäran om implicita typer av typer. Detsamma är regeln i insatsen (Infoga) av värden i fältet eller uppdateringen (uppdatering).

När du jämför rader är det värt att med tanke på det ögonblick som, beroende på databasinställningen (Collation), kan raden jämförelse vara som registeroberoende (när "Petrov" \u003d "Petrov") och registrerar-beroende (när "Petrov"<>"Petrov").
I händelse av fallberoende konfiguration, om du vill göra en sökning utan att registrera, kan du till exempel göra en preliminär omvandling av höger och vänster uttryck till ett register - övre eller nedre:

Välj ID, namn från anställda var övre (namn) som övre (n "pet%") - eller lägre som lägre (n "pet%") Välj ID, efternamn från anställda där övre (efternamn) \u003d övre (n "Petrov" ) - eller lägre (efternamn) \u003d lägre (n "petrov")

Lite om datum

När du checkar på datumet kan du använda, som med linjer med enkla citat "...".

Oavsett de regionala inställningarna i MS SQL kan du använda följande "Yyyymmmdd" -datum (år, månad, skikt av utan mellanslag). Ett sådant datumformat MS SQL kommer alltid att förstå:

Välj ID, namn, födelsedag från anställda där födelsedag mellan "19800101" och "19891231" - anställda i 80-talet Beställ med Birtday

I vissa fall är datumet bekvämare att ange med datumfromparts-funktionen:

Välj ID, namn, födelsedag från anställda där födelsedag mellan DateFromparts (1980,1,1) och datumfromparts (1989,12,31) Beställning av födelsedagen

Det finns också en liknande DateTimeFromparts-funktion, som tjänar till uppgift datum och tid (för typdatimet).

Du kan också använda den konvertera funktionen om du vill konvertera en sträng till värdet av typ eller datetime:

Välj Konvertera (datum, "12.03.2015", 104), konvertera (DateTime, 2014-11-30 17:20:15 ", 120)

Värden 104 och 120 anger vilket datumformat som används i strängen. Du kan hitta en beskrivning av alla giltiga format i MSDN-biblioteket som en sökning efter "MS SQL Convert" -sökning.

Funktioner att arbeta med datum i MS SQL är mycket, leta efter "MS SQL-funktioner för att arbeta med datum."

Notera. I alla dialekter av SQL-språket är din uppsättning funktioner för att arbeta med datum och tillämpar sitt sätt att arbeta med dem.

Lite om siffror och deras omvandlingar

Informationen i det här avsnittet kommer troligen att vara mer användbar för IT-specialister. Om du inte är tillgänglig, och ditt mål helt enkelt kommer att lära dig att skriva förfrågningar om att få information från den databas du behöver, kan sådana subtiliteter inte behövas och du behöver inte, men i alla fall kan du springa längs texten och ta något att notera, för. Om du tog upp studien av SQL, så minns du redan.

Till skillnad från Cast Conversion-funktionen kan du ställa in den tredje parametern i den konvertera funktionen, som är ansvarig för konverteringsstilen (format). För olika typer av data kan din uppsättning stilar användas som kan påverka returresultatet. Vi har redan påverkat användningen av stilar när vi överväger omvandlingen av raden med konverteringsfunktionen i datum och datetime.

Detaljer om de gjutna, konverterade och stilarfunktionerna kan läsas i MSDN - "Cast and Convert (Transact-SQL) funktioner": msdn.microsoft.com/ru-ru/library/ms187928.aspx

För att förenkla exempel kommer Transact-SQL - förklara och ställa in språk att användas här.

Naturligtvis, när det gäller att omvandla ett heltal i den verkliga (som jag tog med början av denna lektion, för att visa skillnaden mellan heltal och real division), är kunskap om omvandlingens nyanser inte så kritisk, eftersom Där gjorde vi omvandlingen av ett heltal till ett verkligt (vars intervall är mycket större än det heltalsintervall):

Förklara @min_int int set @ min_int \u003d -2147483648 förklara @max_int int set @ max_int \u003d 2147483647 Välj - (-2147483648) @ min_int, cast (@min_int som flottör), konvertera (float, @ min_int), - 2147483647 @max_int, cast (@Max_int som flottör), konvertera (float, @ max_int), - numerisk (16,6) @ min_int / 1., - (-2147483648.000000) @ max_int / 1. - 2147483647.000000.

Det kan inte vara värt att ange metoden för implicit transformation som erhållits genom division på (1.), eftersom Det är lämpligt att försöka göra uppenbara omvandlingar för större kontroll över typen av resultat. Även om vi vill få ett resultat av typ numerisk, med det angivna antalet valda nummer, kan vi använda ett knep i MS SQL till (1., 1,0, 1,00, etc.) i MS SQL):

Förklara @ int set @ int \u003d 123 Välj @ int * 1., - Numerisk (12, 0) - 0 tecken efter ett kommatecken @ int * 1.0, - numerisk (13, 1) - 1 tecken @ int * 1.00, - Numerisk (14, 2) - 2 tecken - även om det ibland är bättre att göra en explicit omvandlingsgjuten (@int som numerisk (20, 0)), - 123 gjutning (@int som numeriskt (20, 1)), - 123,0 Gjutna (@int som numeriskt (20, 2)) - 123,00

I vissa fall kan detaljerna i omvandlingen vara väldigt viktig, för De påverkar korrektheten av det erhållna resultatet, exempelvis i fallet när det numeriska värdet omvandlas till strängen (Varchar). Tänk på exempel på att konvertera pengar och flytvärden i Varchar:

Beteende när man konverterar pengar i Varchar Förklara @Money Money Set @Money \u003d 1025.123456789 - En implicit omvandling kommer att ske i 1025.1235, eftersom Pengar typ Butiker Endast 4 siffror efter sömnad Välj @Money, - 1025.1235 - Som standard, gjutna och konvertera uppför sig samma (dvs grovt talande, stil 0) gjuten (@Money AS Varchar (20)), - 1025.12 Konvertera (Varchar (20 ), @Money), - 1025.12 Konvertera (Varchar (20), @Money, 0), - 1025,12 (Stil 0 - Utan tusen tusen och 2-sökta nummer (standardformat)) Konvertera (Varchar (20), @Money , 1), - 1,025,12 (Stil 1 - Tusentals tusen och 2 siffror efter ett kommatecken) Konvertera (Varchar (20), @Money, 2) - 1025.1235 (Style 2 - Ingen separator och 4 kycklingfigur)

Beteende när man konverterar flottör till Varchar Förklara @ float1 float set @ float1 \u003d 1025.123456789 förklara @ float2 float set @ float2 \u003d 1231025.123456789 Välj @ float1 @ float2, - 1231025.12345679 - Standardgjutning och omvandling uppför sig samma (dvs. e. Grovt tala Stil 0) - Stil 0 - Inte mer än 6 siffror. Om det behövs används den exponentiella representationen av siffrorna - när konvertering till Varchar, är det verkligen hemska saker som kastas (@ Float1 som Varchar (20)), - 1025.12 Konvertera (Varchar (20), @ float1), - 1025.12 Konvertera ( Varchar (20), @ float1, 0), - 1025,12 Cast (@ float2 som varchar (20)), - 1,23103E + 006 konvertera (Varchar (20), @ float2), - 1,23103E + 006 konvertera (Varchar (20 ), @ Float2, 0), - 1,23103E + 006 - Style 1 - alltid 8 urladdningar. Den exponentiella representationen av siffror används alltid. - Denna stil för flottör är inte heller mycket exakt omvandlare (Varchar (20), @ float1, 1), - 1.0251235e + 003 konvertera (Varchar (20), @ float2, 1), - 1.2310251E + 006 - Style 2 - Alltid 16 urladdningar. Den exponentiella representationen av siffror används alltid. - Här är noggrannheten hos den redan bättre konverteraren (Varchar (30), @ float1, 2), - 1.025123456789000e + 003 - OK konvertera (Varchar (30), @ float2, 2) - 1.231025123456789e + 006 - OK

Som det kan ses från exemplet kan flytande typer av flottör, i vissa fall verkligen skapa ett större fel, speciellt när destillation i strängen och baksidan (detta kan vara med olika typer av integreringar när data, till exempel sänds i Textfiler från ett system till ett annat).

Om det är nödvändigt att uttryckligen kontrollera noggrannheten till ett visst märke, mer än 4, för att lagra data, ibland är det bättre att använda decimal / numeriska typen. Om det finns tillräckligt med 4 tecken kan du använda penningtypen - det motsvarar ungefär numeriskt (20,4).

Decimal och numerisk förklaring @Money money set @Money \u003d 1025.123456789 - 1025.1235 förklara @ float1 float set @ float1 \u003d 1025.123456789 declare @ float2 float set @ float2 \u003d 1231025.123456789 Förklara @ numeric numeric (28,9) Set @Numeric \u003d 1025.123456789 Välj gjutning (@ @ Numerisk som Varchar (20)) - 1025.12345679 Konvertera (Varchar (20), @Numeric), - 1025,12345679 Cast (@Money AS numeric (28,9)), - 1025,123500000 Cast (@ float1 som numerisk (28, 9)), - 1025,123456789 Cast (@ float2 som numerisk (28,9)) - 12310253456789

Notera.
Från MS SQL 2008-versionen kan du istället för design:
  • mS SQL Server
  • Lägg till taggar




    

    2021. gtavrl.ru..