# 使用 C# 获取 SQLite 元数据

> 原文： [http://zetcode.com/db/sqlitecsharp/meta/](http://zetcode.com/db/sqlitecsharp/meta/)

元数据是有关数据库中数据的信息。 SQLite 中的元数据包含有关表和列的信息，我们在其中存储数据。 受 SQL 语句影响的行数是元数据。 结果集中返回的行数和列数也属于元数据。

可以使用`PRAGMA`命令获取 SQLite 中的元数据。 SQLite 对象可能具有属性，即元数据。 最后，我们还可以通过查询 SQLite 系统`sqlite_master`表来获取特定的元数据。

```cs
using System;
using Mono.Data.Sqlite;

public class Example
{

    static void Main() 
    {
        string cs = "URI=file:test.db";

        string nrows = null;

        try {
            Console.Write("Enter rows to fetch: ");
            nrows = Console.ReadLine();
        } catch (FormatException e)
        {
            Console.WriteLine(e.ToString());
        }

        using (SqliteConnection con = new SqliteConnection(cs))
        {
            con.Open();

            using (SqliteCommand cmd = con.CreateCommand())
            {

                cmd.CommandText = "SELECT * FROM Cars LIMIT @Id";
                cmd.Prepare();

                cmd.Parameters.AddWithValue("@Id", Int32.Parse(nrows));

                int cols = 0;
                int rows = 0;

                using (SqliteDataReader rdr = cmd.ExecuteReader())
                {

                    cols = rdr.FieldCount;
                    rows = 0;

                    while (rdr.Read()) 
                    {
                        rows++;
                    }

                    Console.WriteLine("The query fetched {0} rows", rows);
                    Console.WriteLine("Each row has {0} cols", cols);
                }    
            }

            con.Close();
        }
    }
}

```

在上面的示例中，我们获取查询返回的行数和列数。

```cs
try {
    Console.Write("Enter rows to fetch: ");
    nrows = Console.ReadLine();
} catch (FormatException e)
{
    Console.WriteLine(e.ToString());
}

```

该示例要求在命令行上的行数。

```cs
cmd.CommandText = "SELECT * FROM Cars LIMIT @Id";
cmd.Prepare();

cmd.Parameters.AddWithValue("@Id", Int32.Parse(nrows));

```

我们将选定的行限制为提供给程序的数目。

```cs
cols = rdr.FieldCount;

```

返回的列数可以很容易地从`SqliteDataReader`对象的`FieldCount`属性获得。

```cs
while (rdr.Read()) 
{
    rows++;
}

```

我们计算结果集中的行数。

```cs
$ mono fields_rows.exe 
Enter rows to fetch: 4
The query fetched 4 rows
Each row has 3 cols

```

输出。

## 列标题

接下来，我们将展示如何使用数据库表中的数据打印列标题。

```cs
using System;
using Mono.Data.Sqlite;

public class Example
{

    static void Main() 
    {

        string cs = "URI=file:test.db";

        using (SqliteConnection con = new SqliteConnection(cs))
        {
            con.Open();

            string stm = "SELECT * FROM Cars LIMIT 5";

            using (SqliteCommand cmd = new SqliteCommand(stm, con))
            {

                using (SqliteDataReader rdr = cmd.ExecuteReader())
                {
                    Console.WriteLine(String.Format("{0, -3} {1, -8} {2, 8}", 
                        rdr.GetName(0), rdr.GetName(1), rdr.GetName(2)));

                    while (rdr.Read()) 
                    {
                        Console.WriteLine(String.Format("{0, -3} {1, -8} {2, 8}", 
                            rdr.GetInt32(0), rdr.GetString(1), rdr.GetInt32(2)));
                    }
                }
            }

            con.Close();
        }
    }
}

```

在此程序中，我们从`Cars`表中选择 5 行及其列名。

```cs
using (SqliteDataReader rdr = cmd.ExecuteReader())

```

我们创建一个`SqliteDataReader`对象。

```cs
Console.WriteLine(String.Format("{0, -3} {1, -8} {2, 8}", 
    rdr.GetName(0), rdr.GetName(1), rdr.GetName(2)));

```

我们使用阅读器的`GetName()`方法获得列的名称。 `String.Format()`方法用于格式化数据。

```cs
while (rdr.Read()) 
{
    Console.WriteLine(String.Format("{0, -3} {1, -8} {2, 8}", 
        rdr.GetInt32(0), rdr.GetString(1), rdr.GetInt32(2)));
}       

```

我们将 SQL 语句返回的数据打印到终端。

```cs
$ dmcs columns.cs -r:Mono.Data.Sqlite.dll
$ mono columns.exe 
Id  Name        Price
1   Audi        52642
2   Mercedes    57127
3   Skoda        9000
4   Volvo       29000
5   Bentley    350000

```

该程序的输出。

## 受影响的行

在下面的示例中，我们将发现特定的 SQL 命令已进行了多少更改。

```cs
using System;
using Mono.Data.Sqlite;

public class Example
{

    static void Main() 
    {
        string cs = "Data Source=:memory:";

        using (SqliteConnection con = new SqliteConnection(cs))
        {

            con.Open();

            using (SqliteCommand cmd = new SqliteCommand(con))
            {
                cmd.CommandText = "CREATE TABLE Friends(Id INT, Name TEXT)";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "INSERT INTO Friends VALUES(1, 'Tom')";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "INSERT INTO Friends VALUES(2, 'Jane')";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "INSERT INTO Friends VALUES(3, 'Rebekka')";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "INSERT INTO Friends VALUES(4, 'Lucy')";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "INSERT INTO Friends VALUES(5, 'Robert')";
                cmd.ExecuteNonQuery();

                cmd.CommandText = "DELETE FROM Friends WHERE Id IN (3, 4, 5)";
                int n = cmd.ExecuteNonQuery();

                Console.WriteLine("The statement has affected {0} rows", n);

           }

           con.Close();
        }
    }
}

```

我们在内存中创建一个`Friends`表。 在最后一个 SQL 命令中，我们删除三行。 `ExecuteNonQuery()`方法返回受最后一个 SQL 命令影响的行数。

```cs
cmd.CommandText = "DELETE FROM Friends WHERE Id IN (3, 4, 5)";

```

在此 SQL 语句中，我们删除三行。

```cs
int n = cmd.ExecuteNonQuery();

```

我们找出上一条 SQL 语句完成的更改数量。

```cs
$ mono affected.exe 
The statement has affected 3 rows

```

示例输出。

## 表架构

有`GetSchemaTable()`方法，它返回有关每一列的元数据。 它返回许多值，其中包括列名，列大小，基表名或列是否唯一。

```cs
using System;
using System.Data;
using Mono.Data.Sqlite;

public class Example
{

    static void Main() 
    {
        string cs = "URI=file:test.db";

        using(SqliteConnection con = new SqliteConnection(cs)) 
        {
            con.Open();

            string stm = "SELECT * FROM Cars LIMIT 3";   

            using (SqliteCommand cmd = new SqliteCommand(stm, con))
            {

                using (SqliteDataReader rdr = cmd.ExecuteReader())
                {
                    DataTable schemaTable = rdr.GetSchemaTable();

                    foreach (DataRow row in schemaTable.Rows)
                    {
                        foreach (DataColumn col in schemaTable.Columns)
                            Console.WriteLine(col.ColumnName + " = " + row[col]);
                        Console.WriteLine();
                    }
                }
            }

            con.Close();
         }
    }
}

```

该示例打印有关表列的大量元数据。

```cs
DataTable schemaTable = rdr.GetSchemaTable();

```

我们得到架构表。

```cs
foreach (DataRow row in schemaTable.Rows)
{
    foreach (DataColumn col in schemaTable.Columns)
        Console.WriteLine(col.ColumnName + " = " + row[col]);
    Console.WriteLine();
}

```

我们浏览保存元数据的模式表行，并将其打印到控制台。

```cs
$ dmcs schema.cs -r:Mono.Data.Sqlite.dll -r:System.Data.dll
$ mono schema.exe 
ColumnName = Id
ColumnOrdinal = 0
ColumnSize = 8
NumericPrecision = 19
NumericScale = 0
IsUnique = True
IsKey = True
...

```

摘自示例输出。

## 表名

在与元数据有关的最后一个示例中，我们将列出`test.db`数据库中的所有表。

```cs
using System;
using Mono.Data.Sqlite;

public class Example
{

    static void Main() 
    {
        string cs = "URI=file:test.db";

        using (SqliteConnection con = new SqliteConnection(cs))
        {
            con.Open();

            string stm = @"SELECT name FROM sqlite_master
                WHERE type='table' ORDER BY name";   

            using (SqliteCommand cmd = new SqliteCommand(stm, con))
            {
                using (SqliteDataReader rdr = cmd.ExecuteReader())
                {
                    while (rdr.Read()) 
                    {
                        Console.WriteLine(rdr.GetString(0));
                    }
                }
            }    

            con.Close();    
        }
    }
}

```

该代码示例将所选数据库中的所有可用表打印到终端。

```cs
string stm = @"SELECT name FROM sqlite_master
    WHERE type='table' ORDER BY name"; 

```

表名称是从`sqlite_master`表中检索的。

```cs
$ mono tables.exe 
Cars
Friends
Images

```

这些是我们系统上的表。

在 SQLite C# 教程的这一部分中，我们使用了数据库元数据。