L'idea di scrivere questo tip nasce dalla voglia di approfondire le risposte ricevute a questa mia domanda posta nel forum di DNW.
Una volta recuperato l'elenco delle istanze di SQL disponibili nella rete locale (vedi precedente post) è possibile leggere i nomi dei singoli database ad esse collegate eseguendo la query "SELECT Name FROM SysDataBases":
' VB.
' Crea la stringa di connessione all'istanza locale di SQL.
Dim strCnn As String = "Data Source=.\SQLExpress; Integrated Security=True;Connect Timeout=30;User Instance=True"
' Crea il comando di selezione SQL.
Dim strSql As String = "SELECT Name FROM SysDataBases"
Try
' Crea la connessione al database.
Using cnn As New SqlClient.SqlConnection(strCnn)
cnn.Open()
' Crea l'oggetto command per eseguire la query di selezione nel database.
Using cmd As New SqlClient.SqlCommand(strSql, cnn)
' Crea un DataReader per leggere i risultati della query.
Using dr As SqlClient.SqlDataReader = cmd.ExecuteReader
' Popola una nuova DataTable.
Dim tbl As New DataTable
tbl.Load(dr)
' Binda la DataGridView alla DataTable.
Me.DataGridView1.DataSource = tbl
dr.Close()
End Using
End Using
cnn.Close()
End Using
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
// C#.
// Crea la stringa di connessione all'istanza locale di SQL.
string strCnn = "Data Source=.\\SQLExpress; Integrated Security=True;Connect Timeout=30;User Instance=True";
// Crea il comando di selezione SQL.
string strSql = "SELECT Name FROM SysDataBases";
try {
// Crea la connessione al database.
using (SqlClient.SqlConnection cnn = new SqlClient.SqlConnection(strCnn)) {
cnn.Open();
// Crea l'oggetto command per eseguire la query di selezione nel database.
using (SqlClient.SqlCommand cmd = new SqlClient.SqlCommand(strSql, cnn)) {
// Crea un DataReader per leggere i risultati della query.
using (SqlClient.SqlDataReader dr = cmd.ExecuteReader) {
// Popola una nuova DataTable.
DataTable tbl = new DataTable();
tbl.Load(dr);
// Binda la DataGridView alla DataTable.
this.DataGridView1.DataSource = tbl;
dr.Close();
}
}
cnn.Close();
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
Ricordarsi che "solo gli utenti con privilegi amministrativi hanno accesso alle viste e alle tabelle di sistema."
Una volta collegati ad un'istanza è possibile recuperare dai suoi database (permessi permettendo) numerose informazioni sulla loro struttura e sul loro contenuto eseguendo una sola query.
In questo esempio recuperiamo le PK della tabella Costumers di Northwind:
' VB.
' Crea la stringa di connessione al database Northwind.
Dim strCnn As String = "Data Source=.\SQLExpress;" & _
"AttachDbFilename=""C:\SQL Server 2000 Sample Databases\NORTHWND.MDF"";" & _
"Integrated Security=True;Connect Timeout=30;User Instance=True"
' Individua le colonne di chiave primaria della tabella Customers nel database Northwind.
Dim strSql As String = "SELECT i.name AS index_name, ic.index_column_id, " & _
"ic.key_ordinal, c.name AS column_name, " & _
"TYPE_NAME(c.user_type_id) AS column_type, c.is_identity " & _
"FROM sys.indexes AS i INNER JOIN " & _
"sys.index_columns AS ic ON i.object_id = ic.object_id " & _
"AND i.index_id = ic.index_id INNER JOIN " & _
"sys.columns AS c ON ic.object_id = c.object_id " & _
"AND c.column_id = ic.column_id " & _
"WHERE (i.is_primary_key = 1) AND (i.object_id = " & _
"OBJECT_ID('dbo.Customers'))"
// C#.
// Crea la stringa di connessione al database Northwind.
string strCnn = "Data Source=.\\SQLExpress;" + "AttachDbFilename=\"C:\\SQL Server 2000 Sample Databases\\NORTHWND.MDF\";" + "Integrated Security=True;Connect Timeout=30;User Instance=True";
// Individua le colonne di chiave primaria della tabella Customers nel database Northwind.
string strSql = @"
SELECT
i.name AS index_name
, ic.index_column_id
, ic.key_ordinal
, c.name AS column_name
, TYPE_NAME(c.user_type_id) AS column_type
, c.is_identity
FROM
ys.indexes i
INNER JOIN
sys.index_columns ic
ON
i.object_id = ic.object_id
AND
i.index_id = ic.index_id
INNER JOIN
sys.columns c
ON
ic.object_id = c.object_id
AND
c.column_id = ic.column_id
WHERE
(i.is_primary_key = 1)
AND
(i.object_id = OBJECT_ID('dbo.Customers'))
";
Un elenco di query interessanti da eseguire sul catalogo di sistema di SQL lo troviamo a questo indirizzo.
C'è comunque un altro sistema per raggiungere i suddetti risultati, ossia quello di utilizzare il metodo .GetSchema dell'oggetto SqlConnection (versione 2.0 e superiore).
Questo metodo permette di recuperare molte informazioni dall'oggetto SqlConnection senza dover conoscere la sintassi delle query sopra descritte. Richiamandolo e gestendo correttamente i suoi parametri di Overload, crea una nuova DataTable e la popola con tutte le informazioni richieste.
A dire il vero, se si desiderano informazioni complesse (restituite tra l'altro con un certo ordine), l'utilizzo del suo Overload potrebbe risultare alquanto complicato, ma è del tutto banale nel caso si desideri leggere i dati di base.
Per avere un eleco degli schemi che il metodo è in grado di recuperare non bisogna passaregli alcun parametro:
' VB.
...
Dim tbl As DataTable = cnn.GetSchema()
...
// C#.
...
DataTable tbl = cnn.GetSchema();
...
Ogni schema può essere filtrato mediante apposite restrizioni che permettono un'accurata personalizzazione dei risultati ottenuti. L'argomento può diventare vasto e complesso, vi rimando quindi al vostro motore di ricerca preferito per cercare ulteriori approfondimenti su queste impostazioni.
Tornando al nostro caso, possiamo quindi recuperare l'elenco dei database presenti nell'istanza SQL senza utilizzare alcuna query:
' VB.
' Crea la stringa di connessione all'istanza locale di SQL.
Dim strCnn As String = "Data Source=.\SQLExpress; Integrated Security=True;Connect Timeout=30;User Instance=True"
' Si connette al database.
Using cnn As New SqlClient.SqlConnection(strCnn)
cnn.Open()
Dim tbl As DataTable = cnn.GetSchema("DATABASES")
Me.DataGridView1.DataSource = tbl
cnn.Close()
End Using
{
// C#.
// Crea la stringa di connessione all'istanza locale di SQL.
string strCnn = "Data Source=.\\SQLExpress; Integrated Security=True;Connect Timeout=30;User Instance=True";
// Si connette al database.
using (SqlClient.SqlConnection cnn = new SqlClient.SqlConnection(strCnn)) {
cnn.Open();
DataTable tbl = cnn.GetSchema("DATABASES");
this.DataGridView1.DataSource = tbl;
cnn.Close();
}
}