Condividi tramite


DICHIARARE @local_variable (Transact-SQL)

Si applica a:SQL ServerDatabase SQL di AzureIstanza gestita di SQL di AzureAzure Synapse AnalyticsPiattaforma di analisi (PDW)Endpoint di analisi SQL in Microsoft FabricMagazzino in Microsoft FabricDatabase SQL in Microsoft Fabric

Le variabili vengono dichiarate nel corpo di un batch o di una routine con l'istruzione DECLARE e vengono assegnate valori usando un'istruzione SET o SELECT . È possibile dichiarare variabili di cursore con questa istruzione e utilizzarle insieme ad altre istruzioni correlate ai cursori. Dopo la dichiarazione, tutte le variabili vengono inizializzate come NULL, a meno che non venga specificato un valore come parte della dichiarazione.

Convenzioni relative alla sintassi Transact-SQL

Syntax

La sintassi seguente è per SQL Server e database SQL di Azure:

DECLARE
{
  { @local_variable [AS] data_type [ = value ] }
  | { @cursor_variable_name CURSOR }
| { @table_variable_name [AS] <table_type_definition> }
} [ , ...n ]

<table_type_definition> ::=
    TABLE ( { <column_definition> | <table_constraint> | <table_index> } } [ , ...n ] )

<column_definition> ::=
    column_name { scalar_data_type | AS computed_column_expression }
    [ COLLATE collation_name ]
    [ [ DEFAULT constant_expression ] | IDENTITY [ (seed, increment ) ] ]
    [ ROWGUIDCOL ]
    [ <column_constraint> ]
    [ <column_index> ]

<column_constraint> ::=
{
    [ NULL | NOT NULL ]
    { PRIMARY KEY | UNIQUE }
      [ CLUSTERED | NONCLUSTERED ]
      [ WITH FILLFACTOR = fillfactor
        | WITH ( < index_option > [ , ...n ] )
      [ ON { filegroup | "default" } ]
  | [ CHECK ( logical_expression ) ] [ , ...n ]
}

<column_index> ::=
    INDEX index_name [ CLUSTERED | NONCLUSTERED ]
    [ WITH ( <index_option> [ , ... n ] ) ]
    [ ON { partition_scheme_name (column_name )
         | filegroup_name
         | default
         }
    ]
    [ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]

<table_constraint> ::=
{
    { PRIMARY KEY | UNIQUE }
      [ CLUSTERED | NONCLUSTERED ]
      ( column_name [ ASC | DESC ] [ , ...n ]
        [ WITH FILLFACTOR = fillfactor
        | WITH ( <index_option> [ , ...n ] )
  | [ CHECK ( logical_expression ) ] [ , ...n ]
}

<table_index> ::=
{
    {
      INDEX index_name  [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ]
         (column_name [ ASC | DESC ] [ , ... n ] )
    | INDEX index_name CLUSTERED COLUMNSTORE
    | INDEX index_name [ NONCLUSTERED ] COLUMNSTORE ( column_name [ , ... n ] )
    }
    [ WITH ( <index_option> [ , ... n ] ) ]
    [ ON { partition_scheme_name ( column_name )
         | filegroup_name
         | default
         }
    ]
    [ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]
}

<index_option> ::=
{
  PAD_INDEX = { ON | OFF }
  | FILLFACTOR = fillfactor
  | IGNORE_DUP_KEY = { ON | OFF }
  | STATISTICS_NORECOMPUTE = { ON | OFF }
  | STATISTICS_INCREMENTAL = { ON | OFF }
  | ALLOW_ROW_LOCKS = { ON | OFF }
  | ALLOW_PAGE_LOCKS = { ON | OFF }
  | OPTIMIZE_FOR_SEQUENTIAL_KEY = { ON | OFF }
  | COMPRESSION_DELAY = { 0 | delay [ Minutes ] }
  | DATA_COMPRESSION = { NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE }
       [ ON PARTITIONS ( { partition_number_expression | <range> }
       [ , ...n ] ) ]
  | XML_COMPRESSION = { ON | OFF }
      [ ON PARTITIONS ( { <partition_number_expression> | <range> }
      [ , ...n ] ) ] ]
}

La sintassi seguente riguarda Azure Synapse Analytics e Parallel Data Warehouse e Microsoft Fabric:

DECLARE
{ { @local_variable [AS] data_type } [ = value [ COLLATE <collation_name> ] ] } [ , ...n ]

Arguments

@ local_variable

Nome di una variabile. I nomi di variabile devono iniziare con un simbolo di chiocciola (@). I nomi delle variabili locali devono essere conformi alle regole per gli identificatori.

  • data_type

    Qualsiasi tipo di tabella di sistema, CLR (Common Language Runtime) definito dall'utente o tipo di dati alias. Una variabile non può essere di un tipo di dati text, ntext o image.

    Per altre informazioni sui tipi di dati di sistema, vedere Tipi di dati. Per altre informazioni sui tipi clr definiti dall'utente o sui tipi di dati alias, vedere CREATE TYPE.

  • = valore

    Assegna un valore alla variabile inline. Il valore può essere una costante o un'espressione, ma deve corrispondere al tipo di dichiarazione di variabile o deve supportare la conversione implicita in tale tipo. Per altre informazioni, vedere Espressioni.

@ cursor_variable_name

Nome di una variabile di cursore. I nomi delle variabili di cursore devono iniziare con un simbolo di chiocciola (@) e devono essere conformi alle regole per gli identificatori.

  • CURSOR

    Specifica che si tratta di una variabile di cursore locale.

  • @ table_variable_name

    Nome di una variabile di tipo table. I nomi delle variabili devono iniziare con un simbolo di chiocciola (@) e devono essere conformi alle regole per gli identificatori.

  • <table_type_definition>

    Definisce il tipo di dati table. La dichiarazione di tabella include definizioni di colonna, nomi, tipi di dati e vincoli. Gli unici tipi di vincolo consentiti sono PRIMARY KEY, UNIQUE, NULLe CHECK. Non è possibile usare un tipo di dati alias come tipo di dati scalare di una colonna se al tipo è associata una regola o una definizione di valore predefinito.

<table_type_definition>

Subset di informazioni utilizzate per definire una tabella in CREATE TABLE. Queste informazioni includono elementi e definizioni essenziali. Per altre informazioni, vedere CREATE TABLE.

  • n

    Segnaposto che indica che è possibile specificare più variabili e assegnare i relativi valori. Quando si dichiarano variabili di tabella , la variabile di tabella deve essere l'unica variabile dichiarata nell'istruzione DECLARE .

column_name

Nome della colonna della tabella.

  • scalar_data_type

    Specifica che il tipo di dati della colonna è scalare.

  • computed_column_expression

    Espressione che definisce il valore di una colonna calcolata. Viene calcolato da un'espressione usando altre colonne nella stessa tabella. Ad esempio, una colonna calcolata può avere la definizione cost AS price * qty. L'espressione può essere un nome di colonna non calcolata, una costante, una funzione predefinita, una variabile o qualsiasi combinazione di queste opzioni connesse da uno o più operatori. Non può invece essere una sottoquery o una funzione definita dall'utente. Non può inoltre fare riferimento a un tipo CLR definito dall'utente.

[ COLLATE collation_name ]

Specifica le regole di confronto per la colonna. collation_name può essere un nome delle regole di confronto di Windows o un nome di regole di confronto SQL ed è applicabile solo per le colonne dei tipi di dati char, varchar, text, nchar, nvarchar e ntext. Se viene omesso, alla colonna vengono assegnate le regole di confronto del tipo di dati definito dall'utente, se il tipo di dati della colonna è definito dall'utente, oppure le regole di confronto del database corrente.

Per altre informazioni sui nomi delle regole di confronto di Windows e SQL, vedere COLLATE.

DEFAULT

Specifica il valore assegnato alla colonna quando non viene specificato un valore in modo esplicito durante un inserimento. DEFAULT le definizioni possono essere applicate a qualsiasi colonna, ad eccezione delle colonne definite come timestamp o con la IDENTITY proprietà . DEFAULT le definizioni vengono rimosse quando la tabella viene eliminata. Solo un valore costante, ad esempio una stringa di caratteri; una funzione di sistema, ad esempio , SYSTEM_USER()o NULL può essere usata come impostazione predefinita. Per mantenere la compatibilità con le versioni precedenti di SQL Server, è possibile assegnare un nome di vincolo a un oggetto DEFAULT.

  • constant_expression

    Costante, NULLo una funzione di sistema usata come valore predefinito per la colonna.

IDENTITY

Indica che la nuova colonna è una colonna Identity. Quando si aggiunge una nuova riga alla tabella, SQL Server assegna un valore univoco e incrementale alla colonna. Le colonne Identity vengono comunemente usate con PRIMARY KEY vincoli per fungere da identificatore di riga univoco per la tabella. La IDENTITY proprietà può essere assegnata a colonne tinyint, smallint, int, decimal(p,0)o numeric(p,0). Ogni tabella può includere una sola colonna Identity. Le impostazioni predefinite associate e DEFAULT i vincoli non possono essere usati con una colonna Identity. È necessario specificare sia il valore di inizializzazione che l'incremento oppure è possibile omettere entrambi questi valori. In questo secondo caso, il valore predefinito è (1,1).

  • seed

    Valore usato per la prima riga caricata nella tabella.

  • increment

    Valore incrementale aggiunto al valore Identity della riga caricata in precedenza.

ROWGUIDCOL

Specifica che la nuova colonna funge da identificatore di riga univoco globale. Una sola colonna uniqueidentifier per tabella può essere designata come ROWGUIDCOL colonna. La ROWGUIDCOL proprietà può essere assegnata solo a una colonna uniqueidentifier .

NULL | NON NULLO

Indica se il valore Null è ammesso nella variabile. Il valore predefinito è NULL.

CHIAVE PRIMARIA

Vincolo che impone l'integrità di entità per una o più colonne specificate tramite un indice univoco. È possibile creare un solo PRIMARY KEY vincolo per tabella.

UNIQUE

Vincolo che fornisce l'integrità di entità per una o più colonne specificate tramite un indice univoco. Una tabella può avere più UNIQUE vincoli.

CLUSTERED | NON CLUSTER

Indicare che viene creato un indice cluster o non cluster per il PRIMARY KEY vincolo o UNIQUE . PRIMARY KEYI vincoli usano i vincoli e CLUSTERED usano UNIQUENONCLUSTERED.

CLUSTERED può essere specificato per un solo vincolo. Se CLUSTERED viene specificato per un UNIQUE vincolo e viene specificato anche un PRIMARY KEY vincolo, PRIMARY KEY usa NONCLUSTERED.

CHECK

Vincolo che impone l'integrità di dominio tramite la limitazione dei valori che è possibile inserire in una o più colonne.

  • logical_expression

    Espressione logica che restituisce TRUE o FALSE.

<index_option>

Specifica una o più opzioni per l'indice. Non è possibile creare indici in modo esplicito su variabili di tipo table e per le variabili di tipo table non vengono mantenute statistiche. Sql Server 2014 (12.x) ha introdotto la sintassi che consente di creare determinati tipi di indice inline con la definizione della tabella. Usando questa sintassi, è possibile creare indici nelle variabili di tabella come parte della definizione della tabella. In alcuni casi, le prestazioni potrebbero migliorare usando tabelle temporanee, che forniscono invece il supporto completo dell'indice e le statistiche.

Per una descrizione completa di queste opzioni, vedere CREATE TABLE.

Variabili di tabella e stime delle righe

Le variabili di tipo table non includono statistiche di distribuzione In molti casi, Optimizer compila un piano di query presupponendo che la variabile di tabella abbia zero righe o una riga. Per altre informazioni, vedere Tipo di dati table - Limitazioni e restrizioni.

Per questo motivo, è necessario prestare attenzione in caso di utilizzo di una variabile di tabella se si prevede un numero elevato di righe (maggiore di 100). Considerare una delle alternative seguenti:

  • Le tabelle temporanee possono essere una soluzione migliore rispetto alle variabili di tabella quando è possibile che il conteggio delle righe sia maggiore di 100.

  • Per le query che uniscono la variabile di tabella con altre tabelle, usare l'hint RECOMPILE , che fa sì che l'utilità di ottimizzazione usi la cardinalità corretta per la variabile di tabella.

  • Nel database SQL di Azure e a partire da SQL Server 2019 (15.x), la funzionalità di compilazione posticipata delle variabili di tabella propaga stime di cardinalità basate sui conteggi effettivi delle righe delle variabili di tabella, fornendo un conteggio più accurato delle righe per ottimizzare il piano di esecuzione. Per altre informazioni, vedere Elaborazione di query intelligenti nei database SQL.

Remarks

Le variabili vengono spesso usate in un batch o in una routine come contatori per WHILE, LOOPo per un IF...ELSE blocco.

Le variabili possono essere utilizzate solo nelle espressioni e non in sostituzione di parole chiave o nomi di oggetto. Per costruire istruzioni SQL dinamiche, usare EXECUTE.

L'ambito di una variabile locale è il batch in cui viene dichiarata.

Una variabile di tabella non è necessariamente residente in memoria. In situazioni di utilizzo elevato di memoria è possibile che per le pagine appartenenti a una variabile di tabella venga eseguito il push a tempdb.

È possibile definire un indice inline in una variabile di tabella.

Nelle seguenti istruzioni è possibile fare riferimento come origine a una variabile di cursore a cui è assegnato un cursore:

  • CLOSE affermazione
  • DEALLOCATE affermazione
  • FETCH affermazione
  • OPEN affermazione
  • DELETE Posizione o UPDATE istruzione
  • SET CURSOR istruzione variable (sul lato destro)

Se la variabile di cursore a cui viene fatto riferimento in queste istruzioni esiste ma non le è stato assegnato un cursore, SQL Server genera un errore. Se la variabile di cursore a cui viene fatto riferimento non esiste, SQL Server restituisce lo stesso errore generato per le variabili non dichiarate di altro tipo.

Una variabile di cursore:

  • Può essere la destinazione di un tipo di cursore o di un'altra variabile di cursore. Per ulteriori informazioni, vedere SET @local_variable.

  • È possibile fare riferimento come destinazione di un parametro del cursore di output in un'istruzione EXECUTE se la variabile di cursore non ha un cursore attualmente assegnato.

  • Deve essere considerata come puntatore al cursore.

Examples

Gli esempi di codice in questo articolo usano il AdventureWorks2025 database di esempio o AdventureWorksDW2025 , che è possibile scaricare dalla home page degli esempi di Microsoft SQL Server e dei progetti della community .

A. Usare DECLARE

Nell'esempio seguente viene usata una variabile locale denominata @find per recuperare le informazioni di contatto per tutti i nomi di famiglia che iniziano con Man.

USE AdventureWorks2022;
GO

DECLARE @find AS VARCHAR (30);
/* Also allowed:
DECLARE @find VARCHAR(30) = 'Man%';
*/

SET @find = 'Man%';

SELECT p.LastName,
       p.FirstName,
       ph.PhoneNumber
FROM Person.Person AS p
     INNER JOIN Person.PersonPhone AS ph
         ON p.BusinessEntityID = ph.BusinessEntityID
WHERE LastName LIKE @find;

Il set di risultati è il seguente.

LastName            FirstName               Phone
------------------- ----------------------- -------------------------
Manchepalli         Ajay                    1 (11) 500 555-0174
Manek               Parul                   1 (11) 500 555-0146
Manzanares          Tomas                   1 (11) 500 555-0178

B. Usare DECLARE con due variabili

Nell'esempio seguente vengono recuperati i nomi dei rappresentanti di Adventure Works Cycles che svolgono la propria attività in America del Nord e per cui l'ammontare delle vendite annue è pari almeno a $ 2.000.000.

USE AdventureWorks2022;
GO

SET NOCOUNT ON;
GO

DECLARE @Group AS NVARCHAR (50), @Sales AS MONEY;

SET @Group = N'North America';
SET @Sales = 2000000;
SET NOCOUNT OFF;

SELECT FirstName,
       LastName,
       SalesYTD
FROM Sales.vSalesPerson
WHERE TerritoryGroup = @Group
      AND SalesYTD >= @Sales;

C. Dichiarare una variabile di tipo table

Nell'esempio seguente viene creata una table variabile che archivia i valori specificati nella OUTPUT clausola dell'istruzione UPDATE . Questa variabile è seguita da due istruzioni SELECT che restituiscono i valori in @MyTableVar e i risultati dell'operazione di aggiornamento nella tabella Employee. I risultati nella colonna INSERTED.ModifiedDate sono diversi rispetto ai valori nella colonna ModifiedDate della tabella Employee. Questo perché nella tabella AFTER UPDATE è stato definito il trigger ModifiedDate, che aggiorna il valore di Employee in base alla data corrente. Le colonne restituite da OUTPUT, tuttavia, riflettono i dati prima dell'attivazione dei trigger. Per altre informazioni, vedere Clausola OUTPUT.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    EmpID INT NOT NULL,
    OldVacationHours INT,
    NewVacationHours INT,
    ModifiedDate DATETIME);

UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25
OUTPUT INSERTED.BusinessEntityID,
    DELETED.VacationHours,
    INSERTED.VacationHours,
    INSERTED.ModifiedDate
INTO @MyTableVar;

--Display the result set of the table variable.
SELECT EmpID,
       OldVacationHours,
       NewVacationHours,
       ModifiedDate
FROM @MyTableVar;
GO

--Display the result set of the table.
--Note that ModifiedDate reflects the value generated by an
--AFTER UPDATE trigger.
SELECT TOP (10) BusinessEntityID,
                VacationHours,
                ModifiedDate
FROM HumanResources.Employee;
GO

D. Dichiarare una variabile di tipo table, con indici inline

Nell'esempio seguente viene creata una variabile table con un indice inline cluster e due indici inline non cluster.

DECLARE @MyTableVar TABLE (
    EmpID INT NOT NULL,
    PRIMARY KEY CLUSTERED (EmpID),
    UNIQUE NONCLUSTERED (EmpID),
    INDEX CustomNonClusteredIndex NONCLUSTERED (EmpID));
GO

La query che segue restituisce informazioni sugli indici creati nella query precedente.

SELECT * FROM tempdb.sys.indexes
WHERE object_id < 0;
GO

E. Dichiarare una variabile di tipo tabella definito dall'utente

Nell'esempio seguente viene creato un parametro con valori di tabella o una variabile di tabella denominata @LocationTVP. Questo passaggio richiede un tipo di tabella definito dall'utente corrispondente denominato LocationTableType.

Per altre informazioni su come creare un tipo di tabella definito dall'utente, vedere CREATE TYPE. Per altre informazioni sui parametri con valori di tabella, vedere Usare parametri con valori di tabella (motore di database).

DECLARE @LocationTVP AS LocationTableType;

Esempi: Azure Synapse Analytics e Piattaforma di strumenti analitici (PDW)

F. Usare DECLARE

Nell'esempio seguente viene usata una variabile locale denominata @find per recuperare le informazioni di contatto per tutti i nomi di famiglia che iniziano con Walt.

-- Uses AdventureWorks
DECLARE @find AS VARCHAR (30);
/* Also allowed:
DECLARE @find VARCHAR(30) = 'Man%';
*/

SET @find = 'Walt%';

SELECT LastName,
       FirstName,
       Phone
FROM DimEmployee
WHERE LastName LIKE @find;

G. Usare DECLARE con due variabili

Nell'esempio seguente vengono recuperate le variabili per specificare il nome e la famiglia dei dipendenti nella DimEmployee tabella.

DECLARE @lastName AS VARCHAR (30),
    @firstName AS VARCHAR (30);

SET @lastName = 'Walt%';
SET @firstName = 'Bryan';

SELECT LastName,
       FirstName,
       Phone
FROM DimEmployee
WHERE LastName LIKE @lastName
      AND FirstName LIKE @firstName;