2015-09-08 7 views
5

के लिए असफल रहा निम्न माइग्रेशन करने की कोशिश:Ecto बनाने अद्वितीय सूचकांक mysql/MariaDB

defmodule Shopper.Repo.Migrations.MakeNameUniqueShopper do 
    use Ecto.Migration 

    def change do 
    create unique_index :shoppers, [:name] 
    end 
end 

इसके अलावा create unique_index :shoppers, [:name], name: :name_unique की कोशिश की, create unique_index :shoppers, [:name], name: "name_unique", और create index(:shoppers, [:name], unique: true)

लेकिन वे समान त्रुटि के साथ विफल:

[info] == Running Shopper.Repo.Migrations.MakeNameUniqueShopper.change/0 forward 

[info] create index shoppers_name_index 
** (Mariaex.Error) (1071): Specified key was too long; max key length is 767 bytes 
    (ecto) lib/ecto/adapters/sql.ex:172: Ecto.Adapters.SQL.query!/5 
    (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3 
... 
... 

त्रुटि के साथ मेरी सहायता करने के लिए किसी भी मदद की बहुत सराहना की जाएगी।

नोट: name क्षेत्र utf8mb4, मेरे स्कीमा

द्वारा निर्दिष्ट है: मैं वाह्य 1.02

उपयोग कर रहा हूँ के बाद से mix phoenix.gen.model

defmodule Shopper.Repo.Migrations.CreateV1.Shopper do 
    use Ecto.Migration 

    def change do 
    create table(:shoppers) do 
     add :name, :string 
     add :oauth_token, :string 

     timestamps 
    end 
    end 
end 

जानकारी बनाया गया पहला प्रवास है

अद्यतन: मुझे पता है कि समाधानको कम करना हैफ़ील्ड लम्बाई, लेकिन इसे फीनिक्स मॉडल और माइग्रेशन के साथ कैसे काम करना है? जैसा कि यह एक स्ट्रिंग की उम्मीद है?

+1

कृपया 'तालिका बनाएं' प्रदान करें ताकि हम विनिर्देशों पर चर्चा कर सकें। –

+0

@ रिकजेम्स मुझे यकीन नहीं है कि यह यहां प्रासंगिक है। यह 'mix phoenix.gen.model' – ardhitama

+0

द्वारा बनाया गया है, हम तालिका के ढांचे को देखे बिना कुंजी में उपयोग किए जा रहे फ़ील्ड को कैसे बता सकते हैं? यही @RickJames पूछ रहा है (अगर मैं सही ढंग से समझ रहा हूं)। –

उत्तर

1

जोसे वालिम को उनके उत्तर के माध्यम से मेरी सहायता करने के लिए धन्यवाद, हालांकि यह उत्तर मेरी समस्या का सही समाधान है।

निम्नलिखित कोड के साथ एक नया वाह्य प्रवास स्क्रिप्ट बनाएं:

defmodule Shopper.Repo.Migrations.MakeNameUniqueShopper do 
    use Ecto.Migration 

    def change do 
    alter table(:shoppers) do 
     modify :name, :string, size: 100 
    end 

    create unique_index :shoppers, [:name], name: :shopper_name_unique 
    end 
end 
3

फ़ील्ड "नाम" बहुत लंबा है। आप यह सुनिश्चित करना चाहिए या तो इसे आकार विकल्प पास करके 767 बाइट्स से कम आकार की है जब यह या सूचकांक क्षेत्र का कोई हिस्सा घोषित:

create unique_index :shoppers, ["name(20)"], name: :shoppers_name_unique 

ध्यान रखें कि आप जब में unique_constraint/2 बुला एक ही नाम देने के लिए की आवश्यकता होगी रखें आपका परिवर्तन

+0

जोड़ा है, मुझे एक फ़ील्ड के बारे में एक बिंदु याद आया है जो 767 बाइट से कम होना चाहिए, जो 'add: name, string' में एक स्ट्रिंग वास्तव में 'वर्कर (255) 'है। लेकिन '[" नाम (20) "]' सही फ़ील्ड नाम नहीं है, इसलिए – ardhitama

+0

में एक और त्रुटि का कारण बनता है, मुझे लगता है कि सही उत्तर इसे पहले नाम (20) 'में माइग्रेट कर देगा, फिर अद्वितीय_इंडेक्स बनाएं: दुकानदार, [: नाम], नाम:: shopper_name_unique' – ardhitama

+0

और ... मेरी स्कीमा utf8mb4 – ardhitama

0

utf8mb4 एन्कोडिंग के साथ कम varchar/पाठ स्तंभ आकार बनाने के लिए एक वैकल्पिक MySQL कॉन्फ़िगर करने के लिए 3072 बाइट्स अधिकतम InnoDB सूचकांक उपसर्ग आकार बढ़ाने के लिए है ।

defmodule Shopper.Repo.Migrations.CreateV1.Shopper do 
    use Ecto.Migration 

    def change do 
    # just needs to be done once 
    execute "SET GLOBAL innodb_file_format = BARRACUDA" 
    execute "SET GLOBAL innodb_file_per_table = ON" 
    execute "SET GLOBAL innodb_large_prefix = ON" 

    # in MySQL 5.7.9 or higher, this sets the default row format 
    # otherwise for all new tables you create, you must manually 
    # alter row_format to dynamic before adding any string/text columns 
    execute "SET GLOBAL innodb_default_row_format = DYNAMIC" 

    # change existing shoppers row format to dynamic 
    execute "ALTER TABLE shoppers ROW_FORMAT = DYNAMIC" 

    create unique_index :shoppers, [:name], name: :shopper_name_unique   
    end 
end 
0

यहां मुद्दा यह है InnoDB के प्रमुख आकार (767 बाइट्स) जो सीधे स्तंभ के चारसेट के संबंध में varchar() कॉलम के संभावित आकार के लिए नक्शे है। यदि आप charset utf8 का उपयोग करते हैं, तो varchar कॉलम अधिकतम 255 वर्णों को स्टोर कर सकता है। यदि आप utf8mb4 का उपयोग करते हैं, तो varchar कॉलम केवल 1 9 1 वर्णों को स्टोर कर सकता है।

इस ब्लॉग पोस्ट में पूरी जानकारी में चला जाता है: https://mathiasbynens.be/notes/mysql-utf8mb4

जबकि सूचकांक को इस नियम को लागू करने, जोस पता चलता है की तरह है, निश्चित रूप से एक possiblity है, मैं आपको अपनी varchar स्तंभ आकार को ठीक करने और शिकायत नहीं CREATE INDEX है कहेंगे

defmodule Shopper.Repo.Migrations.CreateV1.Shopper do 
    use Ecto.Migration 

    def change do 
    create table(:shoppers) do 
     add :name, :varchar, size: 191 
     add :oauth_token, :varchar, size: 191 

     timestamps 
    end 
    create unique_index(:shoppers, [:name]) 
    end 
end 

attention: add :name, :string, size: 191 will not work as ecto maps the :string type directly to varchar(255) in the mysql adapter

मेरी राय है कि वाह्य के mysql एडाप्टर जब अपने मूल प्रकार के :string मानचित्रण को ध्यान में रखना चाहिए चारसेट है: पहली जगह में और एक उचित तालिका स्तंभ लेआउट just like rails does it

संबंधित मुद्दे