如何检索 SQL 表中所有列的所有约束名称

Posted

技术标签:

【中文标题】如何检索 SQL 表中所有列的所有约束名称【英文标题】:How to retreive all Constraint Names for all columns in a SQL table 【发布时间】:2021-01-19 10:29:21 【问题描述】:

我在 SQL 数据库的表中添加了许多列。 现在,当我尝试从此表中的 DROP 列的代码时,我收到一个错误,我必须首先 DROP the constraints 对于我尝试 DROP 的实际列。

所以我的问题是如何为以下列中的列返回所有约束名称: 表:DateTimes(在数据库中:DatabaseTest)。 我用谷歌搜索了这个,但没有找到一个直接的代码示例来说明如何做到这一点。我能找到的行是:"show table status from " + databaseName + " where name = '" + datatableName + "';";

下面的代码不起作用,但我想知道是否可以完成此代码以返回表DateTimes 中所有列的constraint names

谢谢!

    void showContstraintsForTable()
    
        String databaseName = "DatabaseTest";
        String datatableName = "DateTimes";


        using (SqlConnection conn = new SqlConnection(GetConnectionString()))
        
            conn.Open();
            String cmdString = "show table status from " + databaseName + " where name = '" + datatableName + "';";
            using (SqlCommand comm = new SqlCommand(cmdString))
            
                try
                
                    comm.Connection = conn;

                    //How to return all CONSTRAINTS for all columns in this table?

                
                catch (SqlException ex)  MessageBox.Show(ex.ToString()); 
            
        
    
    static private string GetConnectionString()
    
        return "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=C:\\Users\\andre\\source\\repos\\TestDatabaseCreation\\DatabaseTest.mdf;Integrated Security=True;Connect Timeout=30";
    

【问题讨论】:

你的数据库是什么?检索约束名称没有标准,每个数据库的做法不同。 是的,所有谷歌搜索都让我感到困惑:我的数据库是 SQL,数据库的名称是 DatabaseTest 【参考方案1】:

以下获取外键约束,其中一种方法一次获取所有表,而第二种方法仅获取一个表。

希望如果这不是一个确切的解决方案,您可以通过一些代码或 sql 修改提供另一个想法。

原来的SQL来了from this post

我使用 Windows 窗体应用程序来提供视觉效果,但不需要用户界面。

约束信息的容器

public class Constraints

    public string TableName  get; set; 
    public string ConstraintName  get; set; 
    public string ColumnName  get; set; 
    public string ReferencedTable  get; set; 
    public string ReferencedColumn  get; set; 
    public override string ToString() => TableName;

SQL 语句

    public class QueryStatements
    
        /// <summary>
        /// Get all tables with foreign keys
        /// </summary>
        /// <returns></returns>
        public static string ForeignKeysAllTables() =>
            @"
SELECT 
TableName = t.Name,constr.name AS ConstraintName, cols.name AS ColumnName, t2.name AS ReferencedTable, c2.name AS ReferencedColumn
FROM sys.tables t
     INNER JOIN sys.foreign_keys constr ON constr.parent_object_id = t.object_id
     INNER JOIN sys.tables t2 ON t2.object_id = constr.referenced_object_id
     INNER JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = constr.object_id
     INNER JOIN sys.columns cols ON cols.object_id = fkc.parent_object_id AND cols.column_id = fkc.parent_column_id
     INNER JOIN sys.columns c2 ON c2.object_id = fkc.referenced_object_id AND c2.column_id = fkc.referenced_column_id
ORDER BY t.Name, cols.name;

";

        /// <summary>
        /// Get foreign keys for a single table
        /// </summary>
        /// <returns></returns>
        public static string ForeignKeysForSingleTable() =>
            @"
SELECT 
TableName = t.Name,constr.name AS ConstraintName, cols.name AS ColumnName, t2.name AS ReferencedTable, c2.name AS ReferencedColumn
FROM sys.tables t
     INNER JOIN sys.foreign_keys constr ON constr.parent_object_id = t.object_id
     INNER JOIN sys.tables t2 ON t2.object_id = constr.referenced_object_id
     INNER JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = constr.object_id
     INNER JOIN sys.columns cols ON cols.object_id = fkc.parent_object_id AND cols.column_id = fkc.parent_column_id
     INNER JOIN sys.columns c2 ON c2.object_id = fkc.referenced_object_id AND c2.column_id = fkc.referenced_column_id 
WHERE t.name = @TableName
ORDER BY t.Name, cols.name;

";
        /// <summary>
        /// Get all table names in a database
        /// </summary>
        /// <param name="databaseName"></param>
        /// <returns></returns>
        public static string GetTableNames(string databaseName) =>
            $"SELECT TABLE_NAME FROM [databaseName].INFORMATION_SCHEMA.TABLES " + 
            "WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME <> 'sysdiagrams' ORDER BY TABLE_NAME";
    

数据类

public class Informational

    /// <summary>
    /// For a real app the connection string could come
    /// from app.config, adjust as needed
    /// </summary>
    private static string _databaseName = "NorthWind2020";

    private static string _connectionString = 
        "Data Source=.\\SQLEXPRESS;" +
        $"Initial Catalog=_databaseName;" +
        "Integrated Security=True";

    public static List<Constraints> GetAllTablesForeignConstraints() 
    
        var results = new List<Constraints>();

        using (var cn = new SqlConnection ConnectionString = _connectionString)
        

            using (var cmd = new SqlCommand Connection = cn)
            
                cmd.CommandText = QueryStatements.ForeignKeysAllTables();
                cn.Open();

                var reader = cmd.ExecuteReader();

                while (reader.Read())
                
                    results.Add(new Constraints()
                    
                        TableName = reader.GetString(0),
                        ConstraintName = reader.GetString(1),
                        ColumnName = reader.GetString(2),
                        ReferencedTable = reader.GetString(3),
                        ReferencedColumn = reader.GetString(4)
                    );
                
            
        

        return results;

    
    public static List<Constraints> GetTableForeignConstraints(string tableName)
    
        var results = new List<Constraints>();

        using (var cn = new SqlConnection  ConnectionString = _connectionString )
        

            using (var cmd = new SqlCommand  Connection = cn )
            
                cmd.CommandText = QueryStatements.ForeignKeysForSingleTable();
                cmd.Parameters.AddWithValue("@TableName", tableName);

                cn.Open();

                var reader = cmd.ExecuteReader();

                while (reader.Read())
                
                    results.Add(new Constraints()
                    
                        TableName = reader.GetString(0),
                        ConstraintName = reader.GetString(1),
                        ColumnName = reader.GetString(2),
                        ReferencedTable = reader.GetString(3),
                        ReferencedColumn = reader.GetString(4)
                    );
                
            
        

        return results;

    

    public static List<string> GetTableNameList()
    
        var results = new List<string>();

        using (var cn = new SqlConnection ConnectionString = _connectionString)
        
            using (var cmd = new SqlCommand Connection = cn)
            
                cmd.CommandText = QueryStatements.GetTableNames(_databaseName);
                cn.Open();

                var reader = cmd.ExecuteReader();

                while (reader.Read())
                
                    results.Add(reader.GetString(0));
                
            
        

        return results;
    

在表单中,ListBox 加载有表名(并不意味着它们有约束)和一个用于显示信息的 TextBox。通过按钮单击事件检索具有表名称约束的列表框的选择更改或一个表的硬编码示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SqlServerUtilities;

namespace SqlServerUtilitiesFrontEnd

    public partial class Form1 : Form
    
        private List<Constraints> _constraints;
        public Form1()
        
            InitializeComponent();

            Shown += Form1_Shown;
        

        private void Form1_Shown(object sender, EventArgs e)
        
            _constraints = Informational.GetAllTablesForeignConstraints();

            TableNameListBox.DataSource = Informational.GetTableNameList();
            DisplayForeignConstraintNames();

            TableNameListBox.SelectedIndexChanged += TableNameListBox_SelectedIndexChanged;
        

        private void TableNameListBox_SelectedIndexChanged(object sender, EventArgs e)
        
            DisplayForeignConstraintNames();
        

        private void DisplayForeignConstraintNames()
        
            var constraints = _constraints
                .Where(item => item.TableName == TableNameListBox.Text).ToList();

            var sb = new StringBuilder();

            foreach (var constraint in constraints)
            
                sb.AppendLine($"constraint.ConstraintName, constraint.ReferencedColumn");
            

            ResultsTextBox.Text = sb.Length == 0 ? "None" : sb.ToString();
            
        

        private void GetCustomersForeignConstraintsButton_Click(object sender, EventArgs e)
        

            var constraints = Informational.GetTableForeignConstraints("Customers");
            var sb = new StringBuilder();

            foreach (var constraint in constraints)
            
                sb.AppendLine($"constraint.ConstraintName, constraint.ReferencedColumn");
            

            ResultsTextBox.Text = sb.Length == 0 ? "None" : sb.ToString();
        
    

我将所有类放在一个类项目中,因为 Windows 窗体项目用于演示目的,而类项目包含所需的内容。

【讨论】:

谢谢你,这似乎工作得很好。感谢您所做的一切帮助!

以上是关于如何检索 SQL 表中所有列的所有约束名称的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle SQL 中显示表的所有约束的名称

SQL如何从每个连接表中检索最新结果

如何添加 NOT NULL 约束以及列的默认值?

在SQL中,如何用ALTER命令删除表中所有完整性约束,然后再用ALTER命令建立

如何复制临时表中列的默认约束?

如何检索表的值以获取sql中两列的最大值