惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Full Disclosure
博客园 - 三生石上(FineUI控件)
MyScale Blog
MyScale Blog
Apple Machine Learning Research
Apple Machine Learning Research
L
LINUX DO - 最新话题
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
月光博客
月光博客
博客园 - 叶小钗
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
D
DataBreaches.Net
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog RSS Feed
量子位
美团技术团队
Vercel News
Vercel News
Y
Y Combinator Blog
IT之家
IT之家
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
腾讯CDC
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
罗磊的独立博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
博客园 - 司徒正美
N
Netflix TechBlog - Medium
S
Schneier on Security
博客园 - 聂微东
U
Unit 42
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
Latest news
Latest news

Fathom blog RSS

Two database migrations and a divorce - Fathom Analytics Fathom acquires Gauges Announcing: Fathom V4 Shipping faster with more confidence How to fix Stripe payment attempt failed because additional action is required Fathom Analytics has been acquired Google Analytics is deleting all of your historical data I made a mistake Reducing our AWS bill by $100,000 How to Enable and Use Link Tracking Protection in iOS 17 How we built our referral program Why Fathom Analytics doesn’t have a free plan Migrating a 2TB database in 7.5 minutes Can you still export Universal Analytics data? Building our Google Analytics Importer Our Google Analytics Importer is now available SingleStore is now faster on Apple Silicon Your privacy resolutions for 2023 Filter your dashboard by event completions Counting Clicks: A Use Case for Grouping Fathom Events
How to have multiple unique columns in SingleStore
Jack Ellis · 2023-01-04 · via Fathom blog RSS

laravel-tips  Jack Ellis · Jan 4, 2023

You’ve used MySQL for many years and have multiple unique keys set up on your tables. Then your data grows, you say Goodbye to MySQL, and you move to SingleStore. But hold on a minute; SingleStore only allows you to use one unique key per table. And if you’re using an auto-incrementing ID, which most of us are in the Laravel world, your one unique key is gone.

The simple solution

Before I get into this, I will give all credit to Carl Sverre. I told him how I was enforcing uniqueness via atomic locks, and he knew of a better way. Let’s get to it.

Step 1: Modify your users table

Our users table is going to be the create_users_table migration with one modification. We have removed the unique() method on the email field, so the table won’t enforce it.

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email');
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Step 2: Create your email_users table

So this is where the beauty comes in. We can’t enforce email uniqueness on the users table, but we can enforce it on another table. Stay with me, folks.

Schema::create('users_emails', function (Blueprint $table) {
    $table->string('email');
    $table->primary('email');
});

Step 3. Creating a user

We now have two tables involved when creating a user. To keep this simple, let’s imagine we have a static function called registerUser somewhere in our application. This is what we might do:

function registerUser($email, $password) {
    try {
        DB::transaction(function() use ($email, $password) {

            // We create our user as usual
            User::forceCreate([
                'email' => $email,
                'password' => Hash::make($password)
            ]);

            // Now, here's the beautiful part
            // If the email already exists in this table
            // it will throw an exception, enforcing uniqueness
            DB::table('users_emails')
                ->insert(['email' => $email]);
        });
    } catch (\Exception $e) {
        // Handle the exception
    }
}

Step 4: Editing a user

How easy was that? And now, let me show you what we’d do when editing a user.

function changeEmail($userId, $oldEmail, $newEmail) {
    try {
        DB::transaction(function() use ($userId, $oldEmail, $newEmail) {

            // Modify the email in the users table
            User::where('id', $userId)
                ->update(['email' => $newEmail]);

            // We have to delete the email because the primary key is immutable
            DB::table('users_emails')
                ->where('email', $oldEmail)
                ->delete();

            // And then we insert the new email of course
            DB::table('users_emails')
                ->insert(['email' => $newEmail]);
        });
    } catch (\Exception $e) {
        // Handle the exception
    }
}

How epic is that?

Step 5: Deleting a user

And now deleting a user is pretty similar to editing a user.

function deleteUser(User $user) {
    try {
        DB::transaction(function() use ($user) {

            // Delete the users email
            DB::table('users_emails')
                ->where('email', $user->email)
                ->delete();

            // Goodbye my lover, goodbye my friend
            $user->delete();
        });
    } catch (\Exception $e) {
        // Handle the exception. You wouldn't get a "unique" error here though.
    }
}

How cool is that?

My previous recommendation was to use atomic locks to enforce uniqueness, which is acceptable, but this is better. With our transaction approach, there are fewer queries, and things are faster. And uniqueness is enforced by the database.

You have duplicate data, but who cares? Databases are about trade-offs. Technology is about trade-offs. Life is about trade-offs. Throw in 10,000,000 email addresses, but you have the database enforcing uniqueness thanks to your transactions? I’ll take that any day.

Return to the Fathom Analytics blog

Jack Ellis

BIO
Jack Ellis, CTO

Tired of how time consuming and complex Google Analytics can be? Try Fathom Analytics:

Start a free trial