2010-06-11 55 views
5

Tôi muốn đọc dữ liệu từ một bảng có tên được cung cấp bởi người dùng. Vì vậy, trước khi thực sự bắt đầu đọc dữ liệu, tôi muốn kiểm tra xem cơ sở dữ liệu có tồn tại hay không.
Kiểm tra xem bảng có tồn tại trong C#

Tôi đã thấy một vài đoạn mã trên NET yêu cầu thực hiện việc này. Tuy nhiên, tất cả chúng dường như chỉ làm việc cho máy chủ SQL, hoặc cho mysql, hoặc một số triển khai khác. Có cách nào không chung chung để làm điều này?

(Tôi đã riêng rẽ kiểm tra nếu tôi có thể kết nối với cơ sở dữ liệu được cung cấp, vì vậy tôi khá chắc chắn rằng một kết nối có thể được mở cơ sở dữ liệu.)

+0

thể trùng lặp của (http://stackoverflow.com/questions/464474/check-if-a -sql-table-exist) –

+0

@Graphain Có vẻ như là một bản sao, tôi có nên làm gì đó không? – apoorv020

+0

Thông thường chỉ cần đợi những người dùng khác đóng và chuyển hướng nhưng thực sự không phải là vấn đề. –

Trả lời

2

Bạn không thể làm điều này trong một cross-cơ sở dữ liệu đường. Nói chung DDL (có nghĩa là, mã để tạo bảng, chỉ mục, v.v.) hoàn toàn khác với cơ sở dữ liệu đến cơ sở dữ liệu và do đó logic để kiểm tra xem bảng có tồn tại hay không.

tôi sẽ nói câu trả lời đơn giản nhất, tuy nhiên, chỉ đơn giản sẽ là một cái gì đó như:

SELECT * FROM <table> WHERE 1 = 0 

Nếu truy vấn cung cấp cho một lỗi, sau đó bàn không tồn tại. Nếu nó hoạt động (mặc dù nó sẽ trả về 0 hàng) thì bảng đó tồn tại.

Hãy cẩn thận với những gì bạn cho phép người dùng nhập vào. Những gì để ngăn chặn anh ta từ chỉ định "sysusers" như tên bảng (trong SQL Server, đó sẽ là danh sách tất cả người dùng cơ sở dữ liệu)

+1

Dựa vào một lỗi để kiểm tra sự tồn tại của bất cứ điều gì có vẻ như một ý tưởng thực sự xấu! –

+2

Ngược lại, chúng tôi biết rằng truy vấn này không chứa lỗi.Sự phụ thuộc duy nhất là bảng đã cho nên tồn tại trong ngữ cảnh của kết nối đã cho. BẤT K error lỗi nào sẽ biểu thị rằng bảng không thể được truy cập (hoặc một cái gì đó kỳ lạ/ngẫu nhiên không thể xử lý được), vì vậy tôi không thấy bất kỳ vấn đề nào trong việc nêu ra một ngoại lệ được nâng lên với sự thiếu truy cập vào bảng supllied. – apoorv020

+0

@Greg B: Tôi không đồng ý, tôi cho rằng đó là một mẫu rất phổ biến: làm cách nào để bạn kiểm tra tệp tồn tại, ngoại trừ bằng cách cố gắng mở tệp? Làm thế nào để bạn kiểm tra một tên miền là hợp lệ, ngoại trừ bằng cách cố gắng giải quyết nó vào một IP? Làm thế nào để bạn kiểm tra một địa chỉ email là hợp lệ, ngoại trừ bằng cách cố gắng gửi một email đến nó? Và cứ thế ... –

0

Điều đó giống như yêu cầu "có cách chung để lấy dữ liệu liên quan" trong cơ sở dữ liệu . Câu trả lời là tất nhiên không - chỉ "cách chung chung" là có một lớp dữ liệu che giấu các chi tiết thực hiện của nguồn dữ liệu cụ thể của bạn và truy vấn nó một cách thích hợp.

Nếu bạn thực sự hỗ trợ và truy cập nhiều loại cơ sở dữ liệu khác nhau mà không cần Stategy design pattern hoặc cách tiếp cận tương tự, tôi sẽ rất ngạc nhiên.

Điều đó đang được nói, phương pháp tốt nhất là một cái gì đó như chút mã này:

bool exists; 

try 
{ 
    // ANSI SQL way. Works in PostgreSQL, MSSQL, MySQL. 
    var cmd = new OdbcCommand(
     "select case when exists((select * from information_schema.tables where table_name = '" + tableName + "')) then 1 else 0 end"); 

    exists = (int)cmd.ExecuteScalar() == 1; 
} 
catch 
{ 
    try 
    { 
     // Other RDBMS. Graceful degradation 
     exists = true; 
     var cmdOthers = new OdbcCommand("select 1 from " + tableName + " where 1 = 0"); 
     cmdOthers.ExecuteNonQuery(); 
    } 
    catch 
    { 
     exists = false; 
    } 
} 

Nguồn: Check if a SQL table exists

3

Bạn có thể sử dụng gia đình DbConnection.GetSchema phương pháp để truy xuất siêu dữ liệu về cơ sở dữ liệu. Nó sẽ trả về một DataTable với các đối tượng lược đồ. Các kiểu đối tượng chính xác và các giá trị hạn chế có thể khác nhau từ nhà cung cấp đến nhà cung cấp, nhưng tôi chắc chắn bạn có thể thiết lập kiểm tra của bạn cho một bảng cụ thể theo cách sẽ hoạt động trong hầu hết các cơ sở dữ liệu.

Dưới đây là ví dụ về cách sử dụng GetSchema sẽ in tên và chủ sở hữu của mỗi bảng thuộc sở hữu của "tên lược đồ" và được gọi là "tên bảng". Điều này được thử nghiệm chống lại oracle.

static void Main(string[] args) 
{ 
    string providerName = @"System.Data.OracleClient"; 
    string connectionString = @"..."; 

    DbProviderFactory factory = DbProviderFactories.GetFactory(providerName); 
    using (DbConnection connection = factory.CreateConnection()) 
    { 
     connection.ConnectionString = connectionString; 
     connection.Open(); 
     DataTable schemaDataTable = connection.GetSchema("Tables", new string[] { "schema name", "table name" }); 
     foreach (DataColumn column in schemaDataTable.Columns) 
     { 
      Console.Write(column.ColumnName + "\t"); 
     } 
     Console.WriteLine(); 
     foreach (DataRow row in schemaDataTable.Rows) 
     { 
      foreach (object value in row.ItemArray) 
      { 
       Console.Write(value.ToString() + "\t"); 
      } 
      Console.WriteLine(); 
     } 
    } 
} 
+0

Khi một bảng không tồn tại, cả 'OracleConnection' và' SqlConnection', việc thực thi 'GetSchema' sẽ trả về một DataTable với 0 hàng. Kết quả này có thể không thể phân biệt được với bảng tồn tại, nhưng không có cột. Tuy nhiên, các bảng không có cột không được phép trong cả Oracle và SQL Server. Vì vậy, 'bool doesTableExist = (schemaDataTable.Rows.Count == 0)' sẽ làm việc cho bạn. –

0

Bạn có thể làm một cái gì đó như thế này: [. Kiểm tra xem một bảng SQL tồn tại]

string strCheck = "SHOW TABLES LIKE \'tableName\'"; 
       cmd = new MySqlCommand(strCheck, connection); 
       if (connection.State == ConnectionState.Closed) 
       { 
        connection.Open(); 
       } 
       cmd.Prepare(); 
       var reader = cmd.ExecuteReader(); 
       if (reader.HasRows) 
       {        
        Console.WriteLine("Table Exist!"); 
       } 
       else (reader.HasRows) 
       {        
        Console.WriteLine("Table Exist!"); 
       } 
Các vấn đề liên quan