PostgreSQL的应用

步骤1:安装Npgsql
通过NuGet安装Npgsql包:
Install-Package Npgsql

步骤2:编写连接字符串(三种格式都可以)
private static string str = "Host=localhost; Port=5432; Username=postgres; Password=123456; Database=testdb";
private static string str = "HOST=localhost;PORT=5432;DATABASE=testdb;USER ID=postgres;PASSWORD=123456;";
private static string str = ConfigurationManager.ConnectionStrings["PostgreSQLConStr"].ConnectionString;//需要在App.config里配置

步骤3:使用SQL命令创建数据库
注意:创建数据库需要超级用户权限(如postgres用户)或具有创建数据库权限的用户。
CREATE DATABASE newDbName

步骤4:执行CREATE TABLE命令
使用NpgsqlCommand执行创建表的SQL语句。
CREATE TABLE IF NOT EXISTS tableName (Id SERIAL PRIMARY KEY, Name VARCHAR(50) UNIQUE NOT NULL,Class VARCHAR(50) UNIQUE NOT NULL,Age INTEGER,Gender BOOLEAN DEFAULT true,CreateTime TIMESTAMP)

创建数据库示例代码:
using Npgsql;

class Program
{
static void Main()
{
// 连接到默认数据库(如postgres)
private static string connString= "Host=localhost; Port=5432; Username=postgres; Password=123456; Database=testdb";

    using (var conn = new NpgsqlConnection(connString))
    {
        conn.Open();
        
        // 要创建的新数据库名称
        string newDbName = "my_new_database";
        
        // 创建数据库的SQL命令
        // 注意:使用参数化查询防止SQL注入,但数据库名不能参数化,所以这里直接拼接(确保名称安全)
        string sql = $"CREATE DATABASE {EscapeDbName(newDbName)}";
        
        using (var cmd = new NpgsqlCommand(sql, conn))
        {
            try
            {
                cmd.ExecuteNonQuery();
                Console.WriteLine($"Database {newDbName} created successfully.");
            }
            catch (PostgresException ex)
            {
                // 如果数据库已存在,会抛出异常
                if (ex.SqlState == "42P04") // 42P04是数据库已存在的错误代码
                {
                    Console.WriteLine($"Database {newDbName} already exists.");
                }
                else
                {
                    Console.WriteLine($"Error: {ex.Message}");
                }
            }
        }
    }
}

// 辅助方法:转义数据库名(防止SQL注入,仅允许安全字符)
private static string EscapeDbName(string name)
{
    // 只允许字母、数字和下划线(根据实际需求调整)
    if (!System.Text.RegularExpressions.Regex.IsMatch(name, @"^[a-zA-Z0-9_]+$"))
    {
        throw new ArgumentException("Invalid database name");
    }
    return name;
}

}

创建数据表示例代码:
using System;
using Npgsql;

class Program
{
static void Main()
{
// 连接字符串,根据实际情况修改
private static string connString= "Host=localhost; Port=5432; Username=postgres; Password=123456; Database=testdb";

    // 创建表的SQL语句
    string createTableSql = @"
        CREATE TABLE IF NOT EXISTS users (
            id SERIAL PRIMARY KEY,
            username VARCHAR(50) UNIQUE NOT NULL,
            email VARCHAR(100) NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        );
    ";

    using (var conn = new NpgsqlConnection(connString))
    {
        try
        {
            conn.Open();
            Console.WriteLine("Connected to the database!");

            // 创建命令对象
            using (var cmd = new NpgsqlCommand(createTableSql, conn))
            {
                cmd.ExecuteNonQuery();
                Console.WriteLine("Table 'users' created successfully!");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

}

删除数据表示例代码:
using System;
using Npgsql;

class Program
{
static void Main()
{
// 数据库连接字符串
private static string connString= "Host=localhost; Port=5432; Username=postgres; Password=123456; Database=testdb";

    // 要删除的表名
    string tableName = "employees";

    try
    {
        using (var conn = new NpgsqlConnection(connString))
        {
            conn.Open();

            // 使用参数化查询避免SQL注入(表名不能参数化,所以需要验证)
            // 注意:表名不能直接参数化,因此需要验证合法性
            string sql = $"DROP TABLE IF EXISTS {SanitizeTableName(tableName)}";

            using (var cmd = new NpgsqlCommand(sql, conn))
            {
                cmd.ExecuteNonQuery();
                Console.WriteLine($"表 '{tableName}' 删除成功(如果存在)");
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"错误: {ex.Message}");
    }
}

// 简单的表名合法性验证(防止SQL注入)
static string SanitizeTableName(string tableName)
{
    // 只允许字母、数字和下划线(根据实际需要调整)
    if (System.Text.RegularExpressions.Regex.IsMatch(tableName, @"^[a-zA-Z0-9_]+$"))
    {
        return tableName;
    }
    else
    {
        throw new ArgumentException("无效的表名");
    }
}

    ////更安全的做法(使用双引号转义):
    //// 在SanitizeTableName方法中,我们使用双引号将表名括起来,并转义其中的双引号
    //static string SanitizeTableName(string tableName)
    //{
    //    // 替换表名中的双引号为两个双引号(PostgreSQL的转义规则)
    //    string escapedTableName = tableName.Replace("\"", "\"\"");
    //    return $"\"{escapedTableName}\"";
    //}

}

数据表重命名 代码示例:
using System;
using System.Text.RegularExpressions;
using Npgsql;

class TableRenamer
{
static void Main()
{
private static string connString= "Host=localhost; Port=5432; Username=postgres; Password=123456; Database=testdb";
string oldTableName = "employees_old";
string newTableName = "employees_new";

    try
    {
        // 验证表名合法性
        if (!IsValidTableName(oldTableName) || !IsValidTableName(newTableName))
        {
            Console.WriteLine("无效的表名");
            return;
        }

        using (var conn = new NpgsqlConnection(connString))
        {
            conn.Open();
            
            // 安全重命名表
            RenameTableSafely(conn, oldTableName, newTableName);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"错误: {ex.Message}");
    }
}

static void RenameTableSafely(NpgsqlConnection conn, string oldName, string newName)
{
    // 使用参数化查询防止 SQL 注入
    string sql = "ALTER TABLE @oldName RENAME TO @newName";
    
    using (var cmd = new NpgsqlCommand(sql, conn))
    {
        // 添加参数
        cmd.Parameters.AddWithValue("oldName", oldName);
        cmd.Parameters.AddWithValue("newName", newName);
        
        cmd.ExecuteNonQuery();
        Console.WriteLine($"表 '{oldName}' 已重命名为 '{newName}'");
    }
}

// 验证表名是否合法(防止 SQL 注入)
static bool IsValidTableName(string name)
{
    // 只允许字母、数字和下划线
    return Regex.IsMatch(name, @"^[a-zA-Z_][a-zA-Z0-9_]*$");
}

}

插入数据 代码示例(单条数据插入):
using System;
using Npgsql;

class Program
{
static void Main()
{
private static string connString= "Host=localhost; Port=5432; Username=postgres; Password=123456; Database=testdb";

    try
    {
        using (var conn = new NpgsqlConnection(connString))
        {
            conn.Open();
            
            string sql = @"
                INSERT INTO users (username, email, age, created_at)
                VALUES (@username, @email, @age, @createdAt)
            ";
            
            using (var cmd = new NpgsqlCommand(sql, conn))
            {
                cmd.Parameters.AddWithValue("username", "john_doe");
                cmd.Parameters.AddWithValue("email", "john@example.com");
                cmd.Parameters.AddWithValue("age", 30);
                cmd.Parameters.AddWithValue("createdAt", DateTime.UtcNow);
                
                int rowsAffected = cmd.ExecuteNonQuery();
                Console.WriteLine($"成功插入 {rowsAffected} 条记录");
            }
        }
    }
    catch (PostgresException ex)
    {
        Console.WriteLine($"PostgreSQL 错误 ({ex.SqlState}): {ex.Message}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"错误: {ex.Message}");
    }
}

}

插入数据 代码示例(使用循环插入多条数据):
static void InsertMultipleUsers(List users)
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();

    string sql = @"
        INSERT INTO users (username, email, age)
        VALUES (@username, @email, @age)
    ";
    
    foreach (var user in users)
    {
        using (var cmd = new NpgsqlCommand(sql, conn))
        {
            cmd.Parameters.AddWithValue("username", user.Username);
            cmd.Parameters.AddWithValue("email", user.Email);
            cmd.Parameters.AddWithValue("age", user.Age);
            
            cmd.ExecuteNonQuery();
        }
    }
}

}
插入数据 代码示例(使用事务批量插入(推荐)):
static void BulkInsertWithTransaction(List users)
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();

    using (var transaction = conn.BeginTransaction())
    {
        try
        {
            string sql = @"
                INSERT INTO users (username, email, age)
                VALUES (@username, @email, @age)
            ";
            
            foreach (var user in users)
            {
                using (var cmd = new NpgsqlCommand(sql, conn, transaction))
                {
                    cmd.Parameters.AddWithValue("username", user.Username);
                    cmd.Parameters.AddWithValue("email", user.Email);
                    cmd.Parameters.AddWithValue("age", user.Age);
                    
                    cmd.ExecuteNonQuery();
                }
            }
            
            transaction.Commit();
            Console.WriteLine($"成功插入 {users.Count} 条记录");
        }
        catch
        {
            transaction.Rollback();
            throw;
        }
    }
}

}
插入数据 代码示例(插入 JSON 数据):
static void InsertWithJson()
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();

    string sql = @"
        INSERT INTO user_profiles (user_id, profile_data)
        VALUES (@userId, @profileData::jsonb)
    ";
    
    using (var cmd = new NpgsqlCommand(sql, conn))
    {
        cmd.Parameters.AddWithValue("userId", 1);
        
        // JSON 数据
        string jsonData = @"
            {
                ""preferences"": {
                    ""theme"": ""dark"",
                    ""notifications"": true
                },
                ""social_links"": [
                    ""https://twitter.com/johndoe"",
                    ""https://github.com/johndoe""
                ]
            }
        ";
        
        cmd.Parameters.AddWithValue("profileData", jsonData);
        
        cmd.ExecuteNonQuery();
    }
}

}
插入数据 代码示例(插入数组数据):
static void InsertWithArray()
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();

    string sql = @"
        INSERT INTO products (name, tags, prices)
        VALUES (@name, @tags, @prices)
    ";
    
    using (var cmd = new NpgsqlCommand(sql, conn))
    {
        cmd.Parameters.AddWithValue("name", "Laptop");
        
        // 文本数组
        string[] tags = { "electronics", "computers", "gadgets" };
        cmd.Parameters.AddWithValue("tags", tags);
        
        // 数值数组
        decimal[] prices = { 999.99m, 1099.99m, 1299.99m };
        cmd.Parameters.AddWithValue("prices", prices);
        
        cmd.ExecuteNonQuery();
    }
}

}

posted on 2025-10-16 16:05  lyc6921  阅读(25)  评论(0)    收藏  举报

导航