2016年2月1日月曜日

[SQLite]文字数制約

文字数の制約をつけたい。
ひとまず、型の後ろにカッコつけて数字かけばいいのかな?

using System;
using System.Data.SQLite;

namespace SampleCode
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (SQLiteConnection con = new SQLiteConnection("Data Source=:memory:"))
                {
                    con.Open();

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

                        cmd.CommandText = "CREATE TABLE [Sample] (" +
                                          "[data]  TEXT(5) NOT NULL" +
                                          ");";
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "INSERT INTO [Sample] ([name]) VALUES('123456');";
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

あら・・・怒られない。
そもそも、文字数制限をかけれるような話をみたことないもんなぁ。

じゃ、別の方法で行ってみます。
cmd.CommandText = "CREATE TABLE [Sample] (" +
                                          "[data]  TEXT NOT NULL CHECK(LENGTH([data]) <= 5)" +
                                          ");";
怒られた。
constraint failed
CHECK constraint failed: Sample

[SQLite]テーブルが作られてなければ作成する

すでにテーブルが存在しているのに作成してしうとエラーになります。
using System;
using System.Data.SQLite;

namespace SampleCode
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (SQLiteConnection con = new SQLiteConnection("Data Source=Test.db"))
                {
                    con.Open();

                    using (SQLiteCommand cmd = con.CreateCommand())
                    {
                        cmd.CommandText = "CREATE TABLE [Sample](" +
                                          "[name]  TEXT NOT NULL" +
                                          ");";
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

SQL logic error or missing database
table [Sample] already exists

そこで、存在していない場合のみ作成したい時は、
他のDBにもあるように、IF NOT EXISTSをつければよい
cmd.CommandText = "CREATE TABLE IF NOT EXISTS [Sample] (" +
                                      "[name]  TEXT NOT NULL" +
                                      ");";

これなら問題無し。

[SQLite]Unique制約で大文字小文字を同じ物と判定する方法

例えば、このブログのタグもそうですが、SQLiteもSQLITEもsqliteも一つのものとして判断してほしい場合があると思います。

そこでUniqueキー制約をつけてみると・・・
using System;
using System.Data;
using System.Data.SQLite;

namespace SampleCode
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (SQLiteConnection con = new SQLiteConnection("Data Source=:memory:"))
                {
                    con.Open();

                    using (SQLiteCommand cmd = con.CreateCommand())
                    {
                        cmd.CommandText = "CREATE TABLE [Blog](" +
                                          "[tag]  TEXT    NOT NULL, " +
                                          "UNIQUE([tag])" +
                                          ");";
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "INSERT INTO [Blog] ([tag]) VALUES('SQLite');";
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "INSERT INTO [Blog] ([tag]) VALUES('SQLITE');";
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
問題なく入ります。
大文字と小文字を別物として判断しているからです。

そこで、大文字小文字を区別してほしくない列にCOLLATE NOCASEをつけてみます。
using System;
using System.Data;
using System.Data.SQLite;

namespace SampleCode
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (SQLiteConnection con = new SQLiteConnection("Data Source=:memory:"))
                {
                    con.Open();

                    using (SQLiteCommand cmd = con.CreateCommand())
                    {
                        cmd.CommandText = "CREATE TABLE [Blog](" +
                                          "[tag]  TEXT    NOT NULL, " +
                                          "UNIQUE([tag] COLLATE NOCASE)" +
                                          ");";
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "INSERT INTO [Blog] ([tag]) VALUES('SQLite');";
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "INSERT INTO [Blog] ([tag]) VALUES('SQLITE');";
                        cmd.ExecuteNonQuery();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

エラーがでるようになりました。
constraint failed
UNIQUE constraint failed: Blog.tag


もちろん、PRIMARY KEYであっても同じことです。
cmd.CommandText = "CREATE TABLE [Blog](" +
                                        "[tag]  TEXT , " +
                                        "PRIMARY KEY([tag] COLLATE NOCASE)" +
                                        ");";

uniqueじゃないと怒ってくれます。
constraint failed
UNIQUE constraint failed: Blog.tag