জাজানোতে ইউনিকোড স্ট্রিং সংরক্ষণ করার সময় মাইএসকিউএল "ভুল স্ট্রিং মান" ত্রুটি


158

জ্যাঙ্গোর লেখক_ ব্যবহারকারী মডেলটির প্রথম নাম, শেষ নামটি সংরক্ষণ করার চেষ্টা করার সময় আমি অদ্ভুত ত্রুটি বার্তা পেয়েছি।

ব্যর্থ উদাহরণ

user = User.object.create_user(username, email, password)
user.first_name = u'Rytis'
user.last_name = u'Slatkevičius'
user.save()
>>> Incorrect string value: '\xC4\x8Dius' for column 'last_name' at row 104

user.first_name = u'Валерий'
user.last_name = u'Богданов'
user.save()
>>> Incorrect string value: '\xD0\x92\xD0\xB0\xD0\xBB...' for column 'first_name' at row 104

user.first_name = u'Krzysztof'
user.last_name = u'Szukiełojć'
user.save()
>>> Incorrect string value: '\xC5\x82oj\xC4\x87' for column 'last_name' at row 104

সফল উদাহরণ

user.first_name = u'Marcin'
user.last_name = u'Król'
user.save()
>>> SUCCEED

মাইএসকিউএল সেটিংস

mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       | 
| character_set_connection | utf8                       | 
| character_set_database   | utf8                       | 
| character_set_filesystem | binary                     | 
| character_set_results    | utf8                       | 
| character_set_server     | utf8                       | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

টেবিল চরসেট এবং কোলেশন

সারণী auth_user এর utf8_ জেনারাল_সি কোলেশন সহ utf-8 চার্সেট রয়েছে।

আপডেটের আদেশের ফলাফল

UPDATE কমান্ডটি ব্যবহার করে auth_user টেবিলের উপরের মানগুলি আপডেট করার সময় এটি কোনও ত্রুটি বাড়েনি।

mysql> update auth_user set last_name='Slatkevičiusa' where id=1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select last_name from auth_user where id=100;
+---------------+
| last_name     |
+---------------+
| Slatkevi?iusa | 
+---------------+
1 row in set (0.00 sec)

পোস্টগ্রি

উপরের তালিকাভুক্ত ব্যর্থ মানগুলিকে পোস্টগ্র্রেএসকিউএল সারণিতে আপডেট করা যেতে পারে যখন আমি জ্যাঙ্গোতে ডাটাবেস ব্যাকএন্ড স্যুইচ করেছি। এটা অদ্ভুত.

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
...
| utf8     | UTF-8 Unicode               | utf8_general_ci     |      3 | 
...

তবে http://www.postgresql.org/docs/8.1/interactive/multbyte.html থেকে , আমি নিম্নলিখিতটি পেয়েছি:

Name Bytes/Char
UTF8 1-4

এর অর্থ কি ইউনিকোড চরের পোস্টগ্র্রেএসকিউএল-তে 4 বাইট কিন্তু মাইএসকিউএলে 3 বাইট রয়েছে যার ফলে উপরের ত্রুটি হয়েছিল?


2
: এটি একটি মাইএসকিউএল সমস্যা, না জ্যাঙ্গো এর stackoverflow.com/questions/1168036/...
Vanuan

উত্তর:


140

এই উত্তরগুলির কোনওোটাই আমার জন্য সমস্যার সমাধান করেনি। মূল কারণ হচ্ছে:

আপনি মাইএসকিউএল-এ utf-8 অক্ষর সেট সহ 4-বাইট অক্ষর সংরক্ষণ করতে পারবেন না।

মাইএসকিউএল -এ ইউপিএফ -8 অক্ষরের উপর 3 বাইট সীমা রয়েছে (হ্যাঁ, এটি ভ্যাকস, এখানে জ্যাঙ্গো বিকাশকারী খুব সুন্দরভাবে সংক্ষেপিত )

এটি সমাধান করার জন্য আপনার প্রয়োজন:

  1. Utf8mb4 অক্ষর সেট ব্যবহার করতে আপনার মাইএসকিউএল ডাটাবেস, টেবিল এবং কলামগুলি পরিবর্তন করুন (কেবলমাত্র মাইএসকিউএল 5.5 এর পরে উপলব্ধ)
  2. আপনার জ্যাঙ্গো সেটিংস ফাইলে চার্সেটটি নীচে উল্লেখ করুন:

settings.py

DATABASES = {
    'default': {
        'ENGINE':'django.db.backends.mysql',
        ...
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}

দ্রষ্টব্য: আপনার ডাটাবেসটি পুনরায় তৈরি করার সময় আপনি ' নির্দিষ্ট কী খুব দীর্ঘ ছিল ' ইস্যুতে চালিত হতে পারেন ।

সর্বাধিক সম্ভাব্য কারণ হ'ল CharFieldযার সর্বাধিক দৈর্ঘ্য 255 এবং এটিতে কোনও প্রকার সূচক (যেমন অনন্য)। কারণ utf8mb4 utf-8 এর তুলনায় 33% বেশি স্থান ব্যবহার করে আপনার এই ক্ষেত্রগুলিকে 33% আরও ছোট করতে হবে।

এই ক্ষেত্রে, সর্বাধিক দৈর্ঘ্য 255 থেকে 191 এ পরিবর্তন করুন।

বিকল্পভাবে আপনি এই মীমাংসা সরিয়ে নিতে আপনার মাইএসকিউএল কনফিগারেশনটি সম্পাদনা করতে পারেন তবে কিছু জ্যাঙ্গো হ্যাকারি ছাড়াই নয়

আপডেট: আমি কেবল এই সমস্যাটিতে আবার দৌড়েছি এবং পোস্টগ্র্রেএসকিউএল-এ স্যুইচিং শেষ করেছি কারণ আমি আমার VARCHAR191 টি অক্ষর হ্রাস করতে পারিনি ।


13
এই উত্তরটির জন্য উপায়, উপায়, আরও বেশি উপায়ে নেওয়া দরকার। ধন্যবাদ! আসল সমস্যাটি হ'ল আপনার অ্যাপ্লিকেশনটি বছরের পর বছর ধরে চলতে পারে যতক্ষণ না কেউ 4 বাইট চরিত্র প্রবেশ করার চেষ্টা করে।
মাইকেল বাইলস্ট্রা

2
এটি একেবারে সঠিক উত্তর। অপশন সেটিংটি জ্যাঙ্গো ডিকোড ইমোজি অক্ষরগুলি তৈরি করতে এবং তাদের মাইএসকিউএলে সংরক্ষণ করার জন্য গুরুত্বপূর্ণ। এসকিউএল কমান্ডের মাধ্যমে কেবল mysfl চরসেটটি utf8mb4 এ পরিবর্তন করা যথেষ্ট নয়!
জেরিওন

পুরো টেবিলের অক্ষর সেটটি utf8mb4 এ আপডেট করার দরকার নেই। প্রয়োজনীয় কলামগুলির জন্য কেবল অক্ষর সেট আপডেট করুন। এছাড়াও 'charset': 'utf8mb4'জ্যাঙ্গো সেটিংসে বিকল্প, সমালোচনামূলক হিসাবে @Xerion বলেন। অবশেষে, সূচকের সমস্যা একটি গোলযোগ। কলামে সূচিটি সরিয়ে ফেলুন, বা এর দৈর্ঘ্য 191 এর চেয়ে বেশি করবেন না বা এর TextFieldপরিবর্তে ব্যবহার করুন!
রক্যালাইট

2
আমি এই উক্তিটির আপনার লিঙ্কটি ভালবাসি : এটি মাইএসকিউএল উদ্দেশ্যমূলক এবং অপরিবর্তনীয়ভাবে মস্তিষ্ক-ক্ষতিগ্রস্থ হওয়ার অন্য একটি ঘটনা। :)
কিউব্যাক

120

আমার একই সমস্যা ছিল এবং কলামের চরিত্রের সেটটি পরিবর্তন করে এটি সমাধান করেছি। যদিও আপনার ডাটাবেসের একটি ডিফল্ট অক্ষর সেট রয়েছে utf-8আমি মনে করি মাইএসকিউএলে ডাটাবেস কলামগুলির জন্য আলাদা অক্ষর সেট করা সম্ভব possible আমি যে এসকিউএল QUERY ব্যবহার করেছি তা এখানে:

    ALTER TABLE database.table MODIFY COLUMN col VARCHAR(255)
    CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;

14
উফ! আমি সবকিছু সমস্ত অক্ষর সেট পরিবর্তিত আমি পারতাম না হওয়া পর্যন্ত আমি সত্যিই পুনরায় পড়তে এই উত্তর: কলাম তাদের থাকতে পারে নিজের অক্ষর সেট, টেবিল এবং ডাটাবেস স্বাধীন। এটা পাগল এবং ঠিক আমার সমস্যাও ছিল।
মার্কপাস্ক

1
এটি আমার পক্ষে টেক্সটফিল্ড মডেলের ডিফল্টগুলির সাথে মাইএসকিএল ব্যবহার করেও কাজ করে।
ম্যাডপ্রপস

এটি আমার সমস্যার সমাধান করেছে। আমি কেবলমাত্র পরিবর্তনটি হ'ল utf8mb4 এবং utf8mb4_general_ci এর পরিবর্তে utf8 / utf8_general_ci।
মিশাল প্রিজিসুচা

70

আপনার যদি সমস্যা হয় তবে আপনার মাইএসকিএল ডাটাবেসের সমস্ত কলাম স্বয়ংক্রিয়ভাবে পরিবর্তন করতে এখানে অজগর স্ক্রিপ্ট রয়েছে।

#! /usr/bin/env python
import MySQLdb

host = "localhost"
passwd = "passwd"
user = "youruser"
dbname = "yourdbname"

db = MySQLdb.connect(host=host, user=user, passwd=passwd, db=dbname)
cursor = db.cursor()

cursor.execute("ALTER DATABASE `%s` CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'" % dbname)

sql = "SELECT DISTINCT(table_name) FROM information_schema.columns WHERE table_schema = '%s'" % dbname
cursor.execute(sql)

results = cursor.fetchall()
for row in results:
  sql = "ALTER TABLE `%s` convert to character set DEFAULT COLLATE DEFAULT" % (row[0])
  cursor.execute(sql)
db.close()

4
এই সমাধানটি আমার সমস্ত সমস্যাগুলিকে একটি জাঙ্গো অ্যাপ্লিকেশন দিয়ে সমাধান করেছে যা ফাইল এবং ডিরেক্টরি পাথ সংরক্ষণ করে। আপনার জাঙ্গো ডাটাবেস হিসাবে dbname টস এবং এটি চালাতে দিন। মোহন মত কাজ!
ক্রিস

1
আমি db.commit()আগে যোগ না করা পর্যন্ত এই কোডটি আমার পক্ষে কাজ করে না db.close()
মার্ক এর্ডম্যান

1
এই সমাধানটি কি @ মার্কপাশের মন্তব্যে আলোচিত সমস্যাটিকে এড়িয়ে চলে: '... মাইএসকিউএল 5.1 এর 3-বাইট ইউটিএফ 8 চরিত্রের সেটটিতে ইমোজি-র মতো 4-বাইট ইউটিএফ
-8

সমাধান যখন আমাকে রেকর্ড ট্রাটি জাঙ্গো অ্যাডমিন মুছছিল তখন আমাকে সহায়তা করে, হে সম্পাদনা তৈরি করার সময় আমার কোনও সমস্যা হয়নি ... অদ্ভুত! এমনকি আমি সরাসরি ডিবিতে মুছতে সক্ষম হয়েছি
জাভিয়র ভিয়েরা

আমি যখনই মডেলটি পরিবর্তন করি তখনই কি আমার এটি করা উচিত?
ভানুয়ান

25

যদি এটি একটি নতুন প্রকল্প হয় তবে আমি কেবল ডাটাবেসটি ফেলে রেখেছি এবং একটি যথাযথ চরসেট সহ একটি নতুন তৈরি করব:

CREATE DATABASE <dbname> CHARACTER SET utf8;

হাই এই দয়া করে এই প্রশ্নটি পরীক্ষা করতে সহায়তা করুন stackoverflow.com/questions/46348817/…
কিং

আমার ক্ষেত্রে, আমাদের ডিবি ডকার দ্বারা তৈরি করা হয়েছে যাতে ঠিক করার জন্য আমি নিম্নলিখিতটি ডিবিতে যুক্ত করেছি: কমান্ড: আমার রচনা ফাইলটিতে নির্দেশনা:- --character-set-server=utf8
7

1
এর মত সহজ. ধন্যবাদ @ ভানুয়ান
এনকু

যদি এটি কোনও নতুন প্রকল্প না হয়, আমরা ডিবি থেকে ব্যাকআপ পাই, এটি ফেলে এবং utf8 চারসেট দিয়ে পুনরায় তৈরি করি এবং তারপরে ব্যাকআপ পুনরুদ্ধার করি। আমি আমার প্রোজেক্টে এটি করেছি যা নতুন ছিল না ...
মোহাম্মদ রেজা

8

উপরের ত্রুটিগুলি এড়াতে আমি একটি পদ্ধতি বের করেছি।

ডাটাবেসে সংরক্ষণ করুন

user.first_name = u'Rytis'.encode('unicode_escape')
user.last_name = u'Slatkevičius'.encode('unicode_escape')
user.save()
>>> SUCCEED

print user.last_name
>>> Slatkevi\u010dius
print user.last_name.decode('unicode_escape')
>>> Slatkevičius

এটি কি কোনও মাইএসকিউএল টেবিলের মতো স্ট্রিংগুলি সংরক্ষণ এবং প্রদর্শনের জন্য টেমপ্লেটগুলিতে রেন্ডার করার আগে এটি ডিকোড করার একমাত্র পদ্ধতি?


12
আমারও অনুরূপ সমস্যা হচ্ছে, তবে আমি সম্মত হই না যে এটি একটি বৈধ সমাধান। আপনি যখন .encode('unicode_escape')ডাটাবেসে ইউনিকোড অক্ষর সংরক্ষণ করছেন না। আপনি সমস্ত ক্লায়েন্টকে ব্যবহার করার আগে তাদের আনইনকোড করতে বাধ্য করছেন, যার অর্থ এটি জ্যাঙ্গো.এডমিন বা সমস্ত ধরণের অন্যান্য জিনিসগুলির সাথে সঠিকভাবে কাজ করবে না।
মিউদস্কোপ

3
অক্ষরের পরিবর্তে এস্কেপ কোডগুলি সংরক্ষণ করা বিরক্তিকর বলে মনে হচ্ছে, মাইএসকিউএল 5.1 এর 3-বাইট utf8চরিত্রের সেটটিতে ইমোজি হিসাবে 4-বাইট ইউটিএফ -8 অক্ষর সংরক্ষণ করার কয়েকটি উপায়গুলির মধ্যে এটি সম্ভবত ।
মার্কপাস্ক

2
এখানে একটি এনকোডিং utf8mb4রয়েছে যা বেসিক বহুভাষিক প্লেনের চেয়ে বেশি সঞ্চয় করতে দেয়। আমি জানি, আপনি ভাববেন যে ইউনিকোড পুরোপুরি সঞ্চয় করার জন্য "ইউটিএফ 8" এর দরকার। ঠিক আছে, ভাদ্দায়া জানেন, তা না। Dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
মিহাই ড্যানিলা

@ জ্যাক আপনি সম্ভবত যেটি আরও কার্যকর
সেটির

এটি একটি বাস্তবসম্মত কাজ, তবে আমি এটি খুব বেশি ব্যবহার করার পরামর্শ দিই না (@ এমডুস্কোপ দ্বারা পরামর্শ হিসাবে)। আমি এখনও সংরক্ষণ করতে পারি না, উদাহরণস্বরূপ, ইমোজি থেকে মাইএসকিএল ডেটাবেস। কেউ কি এটি সম্পাদন করেছে?
মার্সেলো সার্ডেলিচ

6

আপনি আপনার পাঠ্য ক্ষেত্রের জোটটি UTF8_general_ci এ পরিবর্তন করতে পারেন এবং সমস্যাটি সমাধান হবে।

লক্ষ করুন, জাজানোতে এটি করা যায় না।


1

আপনি ইউনিকোড স্ট্রিংগুলি সংরক্ষণ করার চেষ্টা করছেন না, আপনি ইউটিএফ -8 এনকোডিংয়ে বাইটস্ট্রিংগুলি সংরক্ষণ করার চেষ্টা করছেন। তাদের প্রকৃত ইউনিকোড স্ট্রিং আক্ষরিক করুন:

user.last_name = u'Slatkevičius'

অথবা (যখন আপনার কাছে স্ট্রিং লিটারেল নেই) ইউটিএফ -8 এনকোডিং ব্যবহার করে সেগুলি ডিকোড করুন:

user.last_name = lastname.decode('utf-8')

@ থমাস, আপনি যা বলেছিলেন ঠিক তেমন চেষ্টা করেছি কিন্তু এটি এখনও একই ত্রুটি বাড়িয়ে তোলে।
জ্যাক

0

কেবল আপনার টেবিলটি পরিবর্তন করুন, কোনও কিছুর দরকার নেই। এই কোয়েরিটি কেবল ডাটাবেসে চালান। অক্ষর সেট utf8 টেবিল table_nameকনভার্ট পরিবর্তন করুন

এটা অবশ্যই কাজ করবে।


0

@ এমডপ্রপসের উত্তরের উন্নতি - জ্যাঙ্গো ম্যানেজমেন্ট কমান্ড হিসাবে সমাধান:

import MySQLdb
from django.conf import settings

from django.core.management.base import BaseCommand


class Command(BaseCommand):

    def handle(self, *args, **options):
        host = settings.DATABASES['default']['HOST']
        password = settings.DATABASES['default']['PASSWORD']
        user = settings.DATABASES['default']['USER']
        dbname = settings.DATABASES['default']['NAME']

        db = MySQLdb.connect(host=host, user=user, passwd=password, db=dbname)
        cursor = db.cursor()

        cursor.execute("ALTER DATABASE `%s` CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci'" % dbname)

        sql = "SELECT DISTINCT(table_name) FROM information_schema.columns WHERE table_schema = '%s'" % dbname
        cursor.execute(sql)

        results = cursor.fetchall()
        for row in results:
            print(f'Changing table "{row[0]}"...')
            sql = "ALTER TABLE `%s` convert to character set DEFAULT COLLATE DEFAULT" % (row[0])
            cursor.execute(sql)
        db.close()

আশা করি এটি আমার ছাড়া অন্য কাউকে সহায়তা করে :)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.