MySQL で新しいデータ型を作成できませんでした。クエリを以下に示します
CREATE TYPE PERSON AS OBJECT
(NAME VARCHAR (30),
SSN VARCHAR (9));
MySQLでそれを行うにはどうすればよいですか
それはいけません。MySQL にはユーザー定義型がありません。(少なくとも、現在のバージョンではありません。)
JSON データ型を使用できるようになりました。MySQL は、バージョン 5.7 以降、ネイティブの JSON データ型をサポートしています。8.
他の 2 つの答えは 100% 正しいです。どちらも、新しいスカラー タプル値を定義することはできず、JSON をネイティブ型として使用することで、ほとんどそこに到達できます。
3つの提案があります。まず、getter/setter でサポートされている特定の JSON スキーマを値に強制する方法の提案。2 番目に考えられる解決策は CTE によるものですが、それには書き込み側で追加の作業が必要であり、真のカスタム型の代わりにはなりません。3 番目のアプローチは、最初の 2 つの提案のハイブリッドのようなもので、サブクエリ ルックアップをカプセル化するゲッター/セッターを使用します。
さらに読む前に、以下はナプキンドラフト品質のスケッチを表しています. 何も期待しないでください。2020 年後半以降、MySQL を使用していません。
まず、コンストラクター/ゲッター/セッターのアプローチですが、これを実装するには多少の作業が必要になる可能性が高く、適切に設計されたインデックス作成でさえ、ルックアップのパフォーマンスでネイティブ列と競合することはできず、常により多くの時間がかかりますチャンク/ページ/ディスクのスペースですが、それは 90% の解決策です。C で構造体メソッドを実装する方法と同じように、それを行うと、名前空間の編成のためだけになり、ぎこちなくなります。
delimiter $$;
create function contact_encode(fname text, lname text, phone text, email text)
returns JSON
deterministic
begin
/* validation stuff here? like maybe you care that they're not null
and/or sane values for names and phone numbers and email addresses?
*/
return json_object(
'firstName', fname,
'lastName', lname,
'contactMethod', json_array(
json_object(
'type','phone',
'value',phone
),
json_object(
'type','email',
'value',email
)
)
);
end$$
delimiter ;$$
/* Yep, this approach probably actually sucks
I was going to suggest something like contact_decode(JSON)->values...,
but I forgot that you can't return multiple values from a function.
That's the irony; it'd be easier to use JSON for custom types in
languages that already support return tuples and custom types as relations.
Grrrrr
*/
うーん、うん。これはおそらく、MySQL を使用してカスタム型に到達できる最も近いものです。仮説では、次のようなゲッター/セッター関数のセットは、JSON 値/列の既存の MySQL 8 API を実際に改善すると考えられます。これも純粋に仮説ですが、あるレベルのカプセル化されたロジックを提供するエンコードされた動作を持つセッターの例です。
create function contact_get_name(contact JSON)
.....return concat(contact->>'firstName', ' ',contact->>'lastName')
.....
create function contact_set_name(contact JSON, value text)
....return json_replace(
contact,
'$.firstName', substring_index(value, ' ', 1),
'$.lastName'. substring_index(value, ' ', -1)
)
.....
問題はたくさんあります。それが役に立てば、タイピングは MySQL 開発者としての私にとって深刻な制約ではありませんでした。現在、私は PostgreSQL をデフォルトとして使用する組織で働いていますが、カスタム型は素晴らしいものです (rowtype を返します、私はあなたを見ています)。 PostgreSQL より前の CTE で遊ぶことはできません。とはいえ、以下は MySQL に直接変換されない可能性があります。
「blog_user」というテーブルに列 (id、name、phone、email、username、password、blah-blah-blah .....) があるとします。テーブルのクエリでのテーブルの「カスタム タイプ」の使用呼び出された投稿 (id、author_id、タイトル、....) は次のようになります。
with author as (
select
id,
substring_index(name, ' ', 1) as first_name,
substring_index(name, ' ', -1) as last_name,
email,
concat('###-###-', right(phone, 4)) as phone
from blog_user
) select
concat(first_name, ' ', left(last_name, 1), '.') as name,
title,
yada-yada.....
from author, post
where author.id = post.author_id
and case
when @requested_blog_post is not null
then post.id = @requested_blog_post
when @title_search_term is not null
then post.title like concat('%',@title_search_term,'%')
else false
end
それは望ましい影響を達成し、部分結合として、実際にはかなり透過的でパフォーマンスが向上します...コアクエリのフィルターで使用されるCTEソース列に適切なインデックスがあると仮定します.
パフォーマンスに関しては、CTE を追加してサブクエリを作成し、特定の属性に部分的に結合する後者のアプローチは、JSON アプローチよりもはるかに優れていますが、JSON アプローチは間違いなく一部の人にとってより人間工学的です。いずれにせよ、MySQL で JSON を操作することに慣れています。
3 番目の解決策は、次のように、ID を受け取り、その ID の列の値を返すカスタム getter/setter 関数を定義することです。
create function post_get_author_name(requested_post int)
....
return (
with author as (
....
) select
name
from author, post
where author.id = post.author_id
and post.id = requested_post
limit 1 /*completely unnecessary in this case, but it's a thing I do anyway*/
)
....
このアプローチの難しさは、同じクエリで多数のゲッターを呼び出すことを示唆していることです。これは、ローカル CTE ソリューションよりも客観的にパフォーマンスが悪く、行ローカル JSON を使用した同じ getter/setter アプローチよりもパフォーマンスが悪い可能性があります。
要点は次のとおりです。申し訳ありませんが、カスタム型を使用することはできません。いくつかの近似値があり、数か月前にはあなたの痛みさえ理解できなかったでしょうが、お悔やみ申し上げます. おそらく実行可能な近似値をいくつか用意してください。