最平凡日子 最卑微梦想

达梦数据库tips

一点关于达梦VARCHAR(255)的理解。

某涉及达梦数据库的项目中,从达梦数据库取出来数据后需要和本地的std::unordered_map比对,来和本地平台的enum class属性的类型进行匹配,但是std::string之间比对出现了问题,通过

for (char c : str)
    std::cout << (int)c << " ";
std::cout << std::endl;

输出字符串的每个字符的 ASCII 值,发现ASCII 值后半部分不相同,大概率是达梦数据库针对VARCHAR(255)类型数据兼容性没有做到位,导致ODBC取出来字符串有隐藏的字符。

解决方案如下。

建立StringComparator类,处理std::string比对的情况。

#include <string>
#include <algorithm>
#include <cctype>

class StringComparator {
public:
    enum CompareMode {
        CaseSensitive,      // 区分大小写
        IgnoreCase,         // 忽略大小写
        IgnoreAllSpaces,    // 忽略所有空白
        IgnoreCaseAndSpaces // 忽略大小写和所有空白
    };

    // 构造函数,设置比较模式
    StringComparator(CompareMode mode = IgnoreCaseAndSpaces)
        : m_mode(mode) {}

    // 设置比较模式
    void setMode(CompareMode mode) { m_mode = mode; }

    // 执行比较
    bool compare(const std::string& a, const std::string& b) const {
        std::string sa = trim(a);
        std::string sb = trim(b);

        switch (m_mode) {
            case CaseSensitive:
                return sa == sb;
            case IgnoreCase:
                return toLower(sa) == toLower(sb);
            case IgnoreAllSpaces:
                return removeSpaces(sa) == removeSpaces(sb);
            case IgnoreCaseAndSpaces:
                return toLower(removeSpaces(sa)) == toLower(removeSpaces(sb));
            default:
                return sa == sb;
        }
    }

private:
    CompareMode m_mode;

    // 工具函数
    static std::string trim(const std::string& s) {
        auto start = std::find_if_not(s.begin(), s.end(), ::isspace);
        auto end = std::find_if_not(s.rbegin(), s.rend(), ::isspace).base();
        return (start < end ? std::string(start, end) : "");
    }

    static std::string toLower(const std::string& s) {
        std::string result = s;
        std::transform(result.begin(), result.end(), result.begin(), ::tolower);
        return result;
    }

    static std::string removeSpaces(const std::string& s) {
        std::string result;
        std::copy_if(s.begin(), s.end(), std::back_inserter(result),
                     [](char c){ return !std::isspace(c); });
        return result;
    }
};

应用:

StringComparator cmp(StringComparator::IgnoreCaseAndSpaces);

std::string str1 = "  Hello World ";
std::string str2 = "hello world";

if (cmp.compare(str1, str2)) {
    std::cout << "good match" << std::endl;
} else {
    std::cout << "bad match" << std::endl;
}

// 也可以随时切换比较模式
cmp.setMode(StringComparator::CaseSensitive);
if (cmp.compare(str1, str2)) {
    std::cout << "Strict equality" << std::endl;
}