Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A következőkre vonatkozik:SQL Server
Azure SQL Database
Felügyelt Azure SQL-példány
SQL-adatbázis a Microsoft Fabricben
Ha az adatbázisprojektben elemzi a T-SQL-kódot, egy vagy több figyelmeztetés tervezési problémaként kategorizálható. A következő helyzetek elkerülése érdekében a tervezéssel kapcsolatos problémákat kell elhárítania:
- Az adatbázis későbbi módosításai megszakíthatják az attól függő alkalmazásokat.
- Előfordulhat, hogy a kód nem a várt eredményt hozza létre.
- A kód megszakadhat, ha az SQL Server jövőbeli kiadásaival futtatja.
Általában nem szabad letiltania egy tervezési problémát, mert az akár most, akár a jövőben megtörheti az alkalmazást.
A megadott szabályok a következő tervezési problémákat azonosítják:
- SR0001: Kerülje a SELECT * lehetőséget a tárolt eljárásokban, nézetekben és táblaértékű függvényekben
- SR0008: Fontolja meg a SCOPE_IDENTITY használatát @@IDENTITY helyett
- SR0009: Kerülje az 1 vagy 2 méretű változóhossz-típusok használatát
- SR0010: Ne használjon elavult szintaxist táblák vagy nézetek összekapcsolásakor
- SR0013: A kimeneti paraméter (paraméter) nincs feltöltve az összes kódútvonalban
- SR0014: Adatvesztés akkor fordulhat elő, ha {Type1}-ről a(z) {Type2}-re történik átalakítás
SR0001: A SELECT * elkerülése tárolt eljárásokban, nézetekben és táblaértékű függvényekben
Ha helyettesítő karaktert használ egy tárolt eljárás, nézet vagy tábla értékű függvényben egy tábla vagy nézet összes oszlopának kijelöléséhez, a visszaadott oszlopok száma vagy alakja megváltozhat, ha az alapul szolgáló tábla vagy nézet megváltozik. Az oszlop alakja a típus és a méret kombinációja. Ez a variancia problémákat okozhat a tárolt eljárást, nézetet vagy táblaértékű függvényt használó alkalmazásokban, mert ezek a felhasználók eltérő számú oszlopra számíthatnak.
Szabálysértések kijavítása
A tárolt eljárás, a nézet vagy a táblaértékű függvény felhasználóit megvédheti a sémamódosításoktól, ha a helyettesítő karaktert egy teljes oszlopnévlistára cseréli.
Example
Az alábbi példa először egy [Table2] nevű táblát határoz meg, majd két tárolt eljárást határoz meg. Az első eljárás tartalmaz egy SELECT *, amely megsérti az SR0001 szabályt. A második eljárás elkerüli SELECT *, és explicit módon felsorolja a SELECT utasítás oszlopait.
CREATE TABLE [dbo].[Table2]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL,
[Comment] NVARCHAR (50)
)
ON [PRIMARY]
CREATE PROCEDURE [dbo].[procWithWarning]
AS
BEGIN
-- Contains code that breaks rule SR0001
SELECT *
FROM [dbo].[Table2]
END
CREATE PROCEDURE [dbo].[procFixed]
AS
BEGIN
-- Explicitly lists the column names in a SELECT statement
SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[Comment]
FROM [dbo].[Table2]
END
SR0008: Fontolja meg a SCOPE_IDENTITY használatát @@IDENTITY helyett
Mivel @@IDENTITY globális identitásérték, előfordulhat, hogy az aktuális hatókörön kívül lett frissítve, és váratlan értéket kapott. A triggerek, beleértve a replikációban használt beágyazott triggerek, képesek frissíteni az @@IDENTITY értéket a jelenlegi hatókörön kívül.
Szabálysértések kijavítása
A probléma megoldásához a @@IDENTITY hivatkozásait SCOPE_IDENTITY kell cserélnie, amely a felhasználói utasítás hatókörében a legújabb identitásértéket adja vissza.
Example
Az első példában @@IDENTITY egy tárolt eljárásban használatos, amely adatokat szúr be egy táblába. Ezt követően a rendszer közzéteszi a táblát az egyesítési replikációhoz, amely triggereket ad hozzá a közzétett táblákhoz. Ezért az @@IDENTITY vissza tudja adni a beszúrási művelet során keletkezett értéket egy replikációs rendszertábla helyett a felhasználói táblába.
A Sales.Customer tábla maximális identitásértéke 29483. Ha beszúr egy sort a táblázatba, @@IDENTITY és SCOPE_IDENTITY() különböző értékeket ad vissza. SCOPE_IDENTITY() a beszúrási művelet értékét adja vissza a felhasználói táblába, de @@IDENTITY a beszúrási művelet értékét adja vissza a replikációs rendszer táblájába.
A második példa bemutatja, hogyan férhet hozzá a beszúrt identitásértékhez a SCOPE_IDENTITY() használatával, és hogyan oldhatja fel a figyelmeztetést.
CREATE PROCEDURE [dbo].[ProcedureWithWarning]
@param1 INT,
@param2 NCHAR(1),
@Param3 INT OUTPUT
AS
BEGIN
INSERT INTO Sales.Customer ([TerritoryID],[CustomerType]) VALUES (@param1,@param2);
SELECT @Param3 = @@IDENTITY
END
CREATE PROCEDURE [dbo].[ProcedureFixed]
@param1 INT,
@param2 NCHAR(1),
@param3 INT OUTPUT
AS
BEGIN
INSERT INTO Sales.Customer ([TerritoryID],[CustomerType]) VALUES (@param1,@param2);
SELECT @Param3 = SCOPE_IDENTITY()
END
SR0009: Kerülje az 1 vagy 2 méretű változóhossz-típusok használatát
Ha változó hosszúságú adattípusokat (például VARCHAR, NVARCHAR és VARBINARY) használ, további tárolási költséggel jár az adattípusban tárolt érték hosszának nyomon követése. Emellett a változó hosszúságú oszlopokat a rendszer az összes rögzített hosszúságú oszlop után tárolja, ami hatással lehet a teljesítményre. Figyelmeztetést is kap, ha változóhosszt deklarál, például VARCHAR értéket, de nem ad meg hosszt. Ez a figyelmeztetés azért fordul elő, mert ha nincs meghatározva, az alapértelmezett hossz 1.
Szabálysértések kijavítása
Ha a típus hossza nagyon kicsi (1-es vagy 2-es méret), és konzisztens, deklarálja őket rögzített hosszúságú típusként, például CHAR, NCHAR és BINÁRIS értékként.
Example
Ez a példa két tábla definícióit mutatja be. Az első tábla egy változó hosszúságú karakterláncot hossza 2-re deklarál. A második táblázat ehelyett rögzített hosszúságú sztringet deklarál, ami elkerüli a figyelmeztetést.
CREATE TABLE [dbo].[TableWithWarning]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL PRIMARY KEY,
[c2] INT,
[c3] INT,
[SmallString] VARCHAR(2)
)
ON [PRIMARY]
CREATE TABLE [dbo].[FixedTable]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL PRIMARY KEY,
[c2] INT,
[c3] INT,
[SmallString] CHAR(2)
)
ON [PRIMARY]
A változóhosszúság-típusok adatait a rendszer fizikailag tárolja a rögzített hosszúságú adatok után. Ezért adatáthelyezést fog okozni, ha egy oszlopot változóról rögzített hosszra módosít egy olyan táblában, amely nem üres.
SR0010: Ne használjon elavult szintaxist táblák vagy nézetek összekapcsolásakor
Az elavult szintaxist használó illesztések két kategóriába sorolhatók:
- Belső illesztés: Belső illesztés esetén az összekapcsolt oszlopok értékeit egy összehasonlító operátor (például =, <= >stb.) használatával hasonlítjuk össze. A belső illesztések csak akkor adnak vissza sorokat, ha az egyes táblákból legalább egy sor megfelel az illesztés feltételének.
- Külső illesztés: A külső illesztések a FROM záradékban megadott táblák vagy nézetek legalább egyikének összes sorát visszaadják, amennyiben ezek a sorok megfelelnek a WHERE vagy a HAVING keresési feltételnek. Ha = vagy = külső illesztést ad meg, elavult szintaxist használ.
Szabálysértések kijavítása
A belső illesztés szabálysértésének kijavításához használja a szintaxist INNER JOIN .
Ha egy külső illesztés szabálysértését szeretné kijavítani, használja a megfelelő OUTER JOIN szintaxist. A következő lehetőségek közül választhat:
- BAL OLDALI KÜLSŐ ILLESZTÉS VAGY BAL OLDALI ILLESZTÉS
- JOBB KÜLSŐ ILLESZTÉS VAGY JOBB ILLESZTÉS
Az elavult szintaxisra és a frissített szintaxisra az alábbi példák nyújtanak példákat. Az illesztésekről további információt a Csatlakozások oldalon talál.
Examples
A hat példa a következő lehetőségeket mutatja be:
- Az 1. példa egy belső illesztés elavult szintaxisát mutatja be.
- A 2. példa bemutatja, hogyan frissítheti az 1. példát az aktuális szintaxis használatára.
- A 3. példa egy bal oldali külső illesztés elavult szintaxisát mutatja be.
- A 4. példa bemutatja, hogyan frissíthető a 2. példa az aktuális szintaxis használatára.
- Az 5. példa egy jobb oldali külső illesztés elavult szintaxisát mutatja be.
- A 6. példa bemutatja, hogyan frissítheti az 5. példát az aktuális szintaxis használatára.
-- Example 1: Deprecated syntax for an inner join
SELECT [T2].[c3], [T1].[c3]
FROM [dbo].[Table2] T2, [dbo].[Table1] T1
WHERE [T1].[ID] = [T2].[ID]
-- Example 2: Current syntax for an inner join
SELECT [T2].[c3], [T1].[c3]
FROM [dbo].[Table2] AS T2
INNER JOIN [dbo].[Table1] as T1
ON [T2].[ID] = [T2].[ID]
-- Example 3: Deprecated syntax for a left outer join
SELECT [T2].[c3], [T1].[c3]
FROM [dbo].[Table2] T2, [dbo].[Table1] T1
WHERE [T1].[ID] *= [T2].[ID]
-- Example 4: Fixed syntax for a left outer join
SELECT [T2].[c3], [T1].[c3]
FROM [dbo].[Table2] AS T2
LEFT OUTER JOIN [dbo].[Table1] as T1
ON [T2].[ID] = [T2].[ID]
-- Example 5: Deprecated syntax for a right outer join
SELECT [T2].[c3], [T1].[c3]
FROM [dbo].[Table2] T2, [dbo].[Table1] T1
WHERE [T1].[ID] =* [T2].[ID]
-- Example 6: Fixed syntax for a right outer join
SELECT [T2].[c3], [T1].[c3]
FROM [dbo].[Table2] AS T2
RIGHT OUTER JOIN [dbo].[Table1] as T1
ON [T2].[ID] = [T2].[ID]
SR0013: A kimeneti paraméter (paraméter) nem minden kódútvonalban van kitöltve
Ez a szabály azonosítja azokat a kódot, amelyekben a kimeneti paraméter nem egy vagy több kódútvonal értékére van beállítva a tárolt eljárással vagy függvénnyel. Ez a szabály nem határozza meg, hogy a kimeneti paraméter mely elérési utakon legyen beállítva. Ha több kimeneti paraméternél is jelentkezik ez a probléma, minden paraméterhez egy figyelmeztetés jelenik meg.
Szabálysértések kijavítása
Ezt a problémát kétféleképpen lehet kijavítani. Ezt a problémát a legegyszerűbben akkor háríthatja el, ha a kimeneti paramétereket az eljárás törzsének elején egy alapértelmezett értékre inicializálja. Másik lehetőségként beállíthatja a kimeneti paramétert olyan értékre is az adott kódútvonalakban, amelyekben a paraméter nincs beállítva. Egy összetett eljárás során azonban figyelmen kívül hagyhat egy nem gyakori kódútvonalat.
Important
Ha megad egy értéket az eljárásdeklarációban, például CREATE PROC MyProcedure (@param1 INT = 10 OUTPUT) nem oldja meg a problémát. Az eljárás törzsén belül értéket kell hozzárendelnie a kimeneti paraméterhez.
Example
Az alábbi példa két egyszerű eljárást mutat be. Az első eljárás nem állítja be a kimeneti paraméter értékét. @Sum A második eljárás inicializálja a @Sum paramétert az eljárás elején, ami biztosítja, hogy az érték minden kódútvonalon be legyen állítva.
CREATE PROCEDURE [dbo].[procedureHasWarning]
(
@Value1 BIGINT,
@Value2 INT,
@Value3 INT,
@Sum INT OUTPUT
)
AS
BEGIN
-- No initialization of the output parameter
--
-- Additional statements here.
--
RETURN 0;
END
--
CREATE PROCEDURE [dbo].[procedureFixed]
(
@Value1 BIGINT,
@Value2 INT,
@Value3 INT,
@Sum INT OUTPUT
)
AS
BEGIN
-- Initialize the out parameter
SET @Sum = 0;
--
-- Additional statements here
--
RETURN 0;
END
SR0014: Adatvesztés fordulhat elő a(z) {Type1} és {Type2} közötti öntéskor
Ha az adattípusok nincsenek inkonzisztensen oszlopokhoz, változókhoz vagy paraméterekhez rendelve, a rendszer implicit módon konvertálja őket az objektumokat tartalmazó Transact-SQL kód futtatásakor. Az ilyen típusú átalakítás nem csak csökkenti a teljesítményt, hanem bizonyos esetekben az adatok finom elvesztését is okozza. Előfordulhat például, hogy egy táblavizsgálat akkor fut, ha egy WHERE záradék minden oszlopát konvertálni kell. Még rosszabb, hogy az adatok elveszhetnek, ha egy Unicode-sztring más kódlapot használó ASCII-sztringgé alakul át.
Ez a szabály NEM:
- Ellenőrizze a számított oszlop típusát, mert a típus futási időig nem ismert.
- Elemezzen bármit a CASE utasításon belül. Nem elemzi a CASE utasítás visszatérési értékét sem.
- Az ISNULL-hívás bemeneti paramétereinek vagy visszatérési értékének elemzése
Ez a táblázat az SR0014 szabály által érintett ellenőrzéseket foglalja össze:
| Nyelvi szerkezet | Mi van ellenőrizve? | Example |
|---|---|---|
| Paraméterek alapértelmezett értéke | Paraméter adattípusa |
|
| INDEX-predikátum LÉTREHOZÁSA | A predikátum logikai típusú |
|
| A LEFT vagy a RIGHT függvény argumentumai | Karakterlánc argumentumtípusa és hossza |
|
| A CAST és a CONVERT függvény argumentumai | A kifejezés és a típusok érvényesek |
|
| SET utasítás | A bal és a jobb oldalon kompatibilis típusok vannak |
|
| HA utasítás predikátum | A predikátum logikai típusú |
|
| WHILE utasítás predikátum | A predikátum logikai típusú |
|
| INSERT utasítás | Az értékek és oszlopok helyesek |
|
| WHERE predikátum kiválasztása | A predikátum logikai típusú |
|
| SELECT TOP kifejezés | A kifejezés egész szám vagy lebegőpontos típus |
|
| UPDATE utasítás | A kifejezés és az oszlop kompatibilis típusokkal rendelkezik |
|
| UPDATE predikátum | A predikátum logikai típusú |
|
| TOP-kifejezés FRISSÍTÉSE | A kifejezés egész szám vagy lebegőpontos típus |
|
| PREDIKÁTUM TÖRLÉSE | A predikátum logikai típusú |
|
| DELETE TOP kifejezés | A kifejezés egész szám vagy lebegőpontos típus |
|
| Változó deklarálása | A kezdeti érték és az adattípus kompatibilis |
|
| EXECUTE utasítás argumentumai és visszatérési típusa | Paraméterek és argumentumok |
|
| RETURN utasítás | A RETURN kifejezés kompatibilis adattípussal rendelkezik |
|
| MERGE utasítás feltételei | A feltétel logikai |
|
Szabálysértések kijavítása
Ezeket a problémákat elkerülheti és megoldhatja, ha következetesen rendel hozzá adattípusokat, és explicit módon konvertálja azokat a típusokat, ahol szükség van rájuk. Az adattípusok explicit konvertálásával kapcsolatos további információkért tekintse meg ezt a lapot a Microsoft webhelyén: CAST és CONVERT (Transact-SQL).
Example
Ez a példa két tárolt eljárást mutat be, amelyek adatokat szúrnak be egy táblába. Az első eljárás, a procWithWarning egy adattípus implicit átalakítását eredményezi. A második procFixed eljárás bemutatja, hogyan adhat hozzá explicit átalakítást a teljesítmény maximalizálása és az összes adat megőrzése érdekében.
CREATE TABLE [dbo].[Table2]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL,
[c2] INT NOT NULL,
[c3] BIGINT NOT NULL,
[Comment] VARCHAR (25)
)
ON [PRIMARY]
CREATE PROCEDURE [dbo].[procWithWarning]
(
@Value1 INT,
@Value2 INT,
@Value3 BIGINT,
@Comment CHAR(30)
)
AS
BEGIN
INSERT INTO [Table2] ([c1], [c2], [c3], Comment)
VALUES (@Value1, @Value2, @Value3, @Comment)
END
CREATE PROCEDURE [dbo].[procFixed]
(
@Value1 INT,
@Value2 INT,
@Value3 BIGINT,
@Comment CHAR(10)
)
AS
BEGIN
INSERT INTO [Table2] ([c1], [c2], [c3], Comment)
VALUES (@Value1, @Value2, @Value3, CAST(@Comment AS VARCHAR(25)))
END