# کار با دیتاتایپ JSON در MySQL - قسمت دوم

توابع ایجاد محتوای JSON در قسمت قبل برای ذخیره‌سازی محتوای JSON از string literal استفاده کردیم؛ یعنی در واقع همانند یک مقدار رشته‌ای، فیلد JSON را مقداردهی کردیم: INSERT INTO tableName VALUES ( '{ "n

- Published: 2020-11-09
- Language: fa
- Tags: DNTips
- Canonical: https://sirwan.info/blog/fa/dntips-3266

---

> این نوشته نخستین بار در [دات‌نت تیپس](https://www.dntips.ir/post/3266) منتشر شده است.

<div class="postBody"><div> <b>توابع ایجاد محتوای JSON</b> <br/> </div> <div>در <a href="/blog/fa/dntips-3265/">قسمت قبل</a> برای ذخیره‌سازی محتوای JSON از string literal استفاده کردیم؛ یعنی در واقع همانند یک مقدار رشته‌ای، فیلد JSON را مقداردهی کردیم:</div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">INSERT INTO tableName VALUES (&#10;'{ "name": "User1", "age": 41 }'&#10;);</pre>
 </div>
یک روش دیگر، استفاده از توابع JSON_OBJECT یا JSON_ARRAY میباشد:<div align="left" dir="ltr" style="direction: ltr;"> </div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">INSERT INTO tableName VALUES (&#10; JSON_ARRAY(&#10; JSON_OBJECT(&#10; "id", 1,&#10; "name", "User1",&#10; "age", 31,&#10; "skills", JSON_ARRAY("JS", "DB", "Git"),&#10; "address", JSON_OBJECT(&#10;"country", "Iran",&#10;"city", "Tehran")&#10; ),&#10; JSON_OBJECT(&#10;   "id", 2,&#10;   "name", "User2",&#10;   "age", 31,&#10;   "skills", JSON_ARRAY("C#"),&#10;   "address", JSON_OBJECT(&#10; "country", "Iran",&#10; "city", "Sanandaj"&#10;   )&#10; )&#10; )&#10;);</pre>
 </div> <br/> <div> <br/> </div> <div>در ادامه با یکسری از توابع دیگر کار با آرایه‌ها و بطور کلی با توابعی جهت تغییر محتوای JSON آشنا خواهیم شد.</div> <div> <br/> </div> <div> <b>JSON_ARRAY_APPEND</b> </div> <div>فرض کنید برای کاربر User2 میخواهیم یک آیتم به پراپرتی skills اضافه کنیم. برای اینکار میتوانیم از تابع JSON_ARRAY_APPEND استفاده کنیم: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">UPDATE experiments.tableName &#10;SET jsonData = JSON_ARRAY_APPEND(jsonData,&#10;              '$[1].skills',&#10;              'JS',&#10;              '$[1].skills',&#10;              'DB',&#10;              '$[1].skills',&#10;              'Kotlin'&#10;            )&#10;&#10;-- ["C#", "JS", "DB", "Kotlin"]</pre>
 </div> <br/> </div> <div> <div> <b>JSON_ARRAY_INSERT</b> </div> <div>این تابع نیز شبیه تابع قبلی است؛ با این تفاوت که به جای append کردن مقداری به آخر لیست، میتوانیم این مقدار جدید را در مکان مورد  نظر اضافه کنیم: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">UPDATE experiments.tableName &#10;SET &#10;    jsonData = JSON_ARRAY_INSERT(jsonData, '$[1].skills[4]', 'TS')&#10;    &#10;-- ["C#", "JS", "DB", "Kotlin", "TS"]</pre>
 </div> <br/> </div> <div> <div> <b>JSON_INSERT</b> </div> <div>از این تابع جهت درج یک مقدار جدید به محتوای JSON استفاده میشود. دقت داشته باشید که این تابع مقادیر موجود را overwrite نخواهد کرد و فقط در صورت عدم وجود آن key، مقدار را اضافه میکند: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">UPDATE experiments.tableName &#10;SET &#10;    jsonData = JSON_INSERT(jsonData,&#10;            '$[1].address.location',&#10;            JSON_OBJECT('phone', 8989898))</pre>
 </div> <br/> </div> <div> <div> <b>JSON_REPLACE</b> </div> <div>از این تابع جهت جایگزینی مقادیر استفاده خواهد شد. به عنوان مثال میتوانیم محتوای قبلی را اینگونه به روز کنیم: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">UPDATE experiments.tableName &#10;SET &#10;    jsonData = JSON_REPLACE(jsonData,&#10;            '$[1].address.location.phone',&#10;            12345656)</pre>
 </div> <br/> </div> <div> <div> <b>JSON_REMOVE</b> </div> <div>از این تابع میتوانیم جهت حذف یک مقدار، یا پراپرتی خاصی استفاده کنیم: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">UPDATE experiments.tableName &#10;SET &#10;    jsonData = JSON_REMOVE(jsonData, '$[1].address')</pre>
 </div> <br/> </div> <div> <div> <b>JSON_SET</b> </div> <div>توسط این تابع میتوانیم دیتایی را به محتوای JSON، اضافه یا به‌روزرسانی کنیم. این تابع همانند JSON_INSERT عمل میکند؛ با این تفاوت که در صورت وجود path، مقدار را overwrite خواهد کرد، در غیراینصورت مقدار جدید را اضافه می‌کند: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">UPDATE experiments.tableName &#10;SET &#10;    jsonData = JSON_SET(jsonData,&#10;              '$[1].address',&#10;              JSON_OBJECT('country',&#10;                      'Iran',&#10;                      'city',&#10;                      '-',&#10;                      'phone',&#10;                      12345&#10;              ));&#10;&#10;/*&#10;  { location: { "city": "-", "phone": 12345, "country": "Iran" } }&#10;*/&#10;&#10;UPDATE experiments.tableName &#10;SET &#10;    jsonData = JSON_SET(jsonData,&#10;            '$[1].address.city',&#10;            'Tehran');&#10;&#10;/*&#10;  { location: { "city": "-", "phone": 12345, "country": "Iran" } }&#10;*/&#10;&#10;&#10;UPDATE experiments.tableName &#10;SET jsonData = JSON_SET(jsonData, '$[1].address.postcode', '0098');&#10;&#10;/*&#10;  { location: {"city": "Tehran", "phone": 12345, "country": "Iran", "postcode": '0098' } }&#10;*/</pre>
 </div> <br/> </div> <div> <br/> </div> <div> <div> <b>JSON_UNQUOTE</b> </div> <div>توسط این تابع میتوانیم خروجی را به صورت unquote شده ببینیم. بدون استفاده از این تابع، خروجی داخل quotation میباشد: <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">SELECT &#10;    JSON_EXTRACT(jsonData, '$[1].address.city')&#10;FROM&#10;    experiments.tableName;&#10;    &#10;-- "Tehran"&#10;&#10;SELECT &#10;    JSON_UNQUOTE(JSON_EXTRACT(jsonData, '$[1].address.city'))&#10;FROM&#10;    experiments.tableName;&#10;    &#10;-- Tehran</pre>
 </div> <br/> </div> <div>همانطور که مشاهده میکنید از تابع JSON_EXTRACT برای کوئری گرفتن از پراپرتی city استفاده کرده‌ایم. خروجی تابع را نیز به JSON_UNQUOTE جهت حذف quotation ارسال کرده‌ایم. یک سینتکس دیگر نیز برای خلاصه‌سازی JSON_EXTRACT وجود دارد:  <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">SELECT &#10;    jsonData -&gt; '$[1].address.city'&#10;FROM&#10;    experiments.tableName;&#10;&#10;-- "Tehran"</pre>
 </div> <br/> </div> <div>همچنین برای حذف quoteها میتوانیم اپراتور فوق را اینگونه بنویسیم که همان کار تابع JSON_UNQUOTE را انجام میدهد:  <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">SELECT &#10;    jsonData -&gt;&gt; '$[1].address.city'&#10;FROM&#10;    experiments.tableName;&#10;&#10;-- Tehran</pre>
 </div> <br/> </div> <div> <b>نکته</b>: هر دو حالت را میتوانیم در قسمت WHERE نیز استفاده کنیم:  <br/> </div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">SELECT &#10;    jsonData -&gt;&gt; '$[1].address.city'&#10;FROM&#10;    experiments.tableName&#10;WHERE jsonData -&gt;&gt; '$[1].address.city' = 'Tehran';</pre>
 </div> <br/> </div> <div> <b>ادغام محتوای JSON با یکدیگر</b> </div> <div>در MySQL دو تابع با نامهای JSON_MERGE_PATCH و JSON_MERGE_PRESERVE برای ادغام دو یا چند محتوای JSON وجود دارد. تابع JSON_MERGE_PRESERVE همانطور که از نامش پیداست، مقادیر را نگه میدارد؛ یعنی کلیدهای یکسان را با هم ادغام میکند و مقادیر را به صورت آرایه به عنوان valueی شیء در نظر میگیرد:</div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">SELECT &#10;    JSON_MERGE_PRESERVE('{&#10;                "id": "1",&#10;                "name": "Product One",&#10;                "price": 12.45,&#10;                "discount": 10,&#10;                "rating": 4,&#10;                "category": ["fashion", "men"],&#10;                "tags": ["fashion", "men", "jacket", "full sleeve"]&#10;            }',&#10;            '{&#10;                "id": "2",&#10;                "name": "Product Two",&#10;                "price": 30,&#10;                "discount": 0,&#10;                "rating": 3,&#10;                "category": ["fashion", "men"],&#10;                "tags": ["fashion", "men", "jacket", "full sleeve"]&#10;            }');</pre>
 </div> <br/> </div> <div>خروجی کوئری فوق به اینصورت خواهد بود:</div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="JScript" name="code">{&#10;  "id": ["1", "2"],&#10;  "name": ["Product One", "Product Two"],&#10;  "tags": [&#10;    "fashion",&#10;    "men",&#10;    "jacket",&#10;    "full sleeve",&#10;    "fashion",&#10;    "men",&#10;    "jacket",&#10;    "full sleeve"&#10;  ],&#10;  "price": [12.45, 30],&#10;  "rating": [4, 3],&#10;  "category": ["fashion", "men", "fashion", "men"],&#10;  "discount": [10, 0]&#10;}</pre>
 </div> <br/> </div> <div>اما تابع JSON_MERGE_PATCH در نهایت یک خروجی را خواهد داشت؛ کاری که انجام میدهد به‌روزرسانی (patch) مقدار جدید، با مقدار قبلی است. یعنی کلیدهای آبجکت اول را که در آبجکت دوم قرار دارند، حذف میکند. همچنین کلیدهای جدید را در شیء یکی شده‌ی نهایی نیز اضافه خواهد کرد. به عنوان مثال برای آبجکت اول، یک پراپرتی جدید را با نام sku اضافه کرده‌ایم:</div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="Sql" name="code">SELECT JSON_MERGE_PATCH('{&#10;                "id": "1",&#10;                "name": "Product One",&#10;                "price": 12.45,&#10;                "discount": 10,&#10;                "rating": 4,&#10;                "category": ["fashion", "men"],&#10;                "tags": ["fashion", "men", "jacket", "full sleeve"],&#10;                "sku": "asdf123"&#10;            }',&#10;            '{&#10;                "id": "2",&#10;                "name": "Product Two",&#10;                "price": 30,&#10;                "discount": 0,&#10;                "rating": 3,&#10;                "category": ["fashion", "men"],&#10;                "tags": ["fashion", "men", "jacket", "full sleeve"]&#10;            }');</pre>
 </div> <br/> </div> <div>خروجی کوئری فوق این چنین خواهد بود:</div> <div> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="JScript" name="code">{&#10;  "id": "2",&#10;  "sku": "asdf123",&#10;  "name": "Product Two",&#10;  "tags": ["fashion", "men", "jacket", "full sleeve"],&#10;  "price": 30,&#10;  "rating": 3,&#10;  "category": ["fashion", "men"],&#10;  "discount": 0&#10;}</pre>
 </div> </div> </div> </div> </div> </div> </div> </div></div>
