Как изменить тип поля CCK (integer на текст)

Главные вкладки

Аватар пользователя Valeratal Valeratal 18 ноября 2010 в 10:31

Такой вопрос
достался мне сайт, книжный магазин
там поле "издательство" тип integer

а по логике, должно быть текст

Понятно, что из модуля я уже изменить не могу

Подскажите как это можно сделать. если в базе поискать и вручную?
есть ли подводные камни?

p.s. И где именно менять? (на тот случай если поиском phpmyadmin не найду)

Комментарии

Аватар пользователя Виктор Степаньков ака RxB Виктор Степаньк... 18 ноября 2010 в 12:23

Делаем новое поле текстовое, например, publishertxt, старое просто publisher к примеру
далее выполняем сниппет:

$sql = "SELECT nid from {node} WHERE type = 'book'";
$result = db_query($sql);
while($object = db_fetch_result($result)){
$node = node_load($object->nid);
$node->field_publishertxt[0]['value'] = $node->field_publisher[0]['value'];
node_save($node);
drupal_set_message($node->title.' обновлёно, всё чотко');
unset($node);
}
drupal_set_message('Профит');

как-то так

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 ноября 2010 в 12:46

А не проще сделать одним запросом?
Сначала добавьте поле, потом:

UPDATE content_type_книга SET field_publiser_value = field_id_value

Это если поле только в одном типе материалов.
Если в нескольких, то таблица будет вместо content_type_книга - content_field_publisher

UPD:
Правда, если издательств немного, то интереснее на таксономию переделать.
Там все тоже чисто sql можно преобразовать, словарь только и таксономию к материалу добавить в друпале.

Аватар пользователя G.A. Vinogradov G.A. Vinogradov 18 ноября 2010 в 12:52

А я бы базу правил Wink

1. делаем бэкап
2. таблица content_node_field - находим нужную строчку, меняем поля module и type на text
3. таблица content_node_field_instance - находим нужную строчку, меняем поле widget на text_textfield
4. таблица content_type_[type] - лезем в структуру, меняем тип поля на TEXT или VARCHAR(255).

Аватар пользователя G.A. Vinogradov G.A. Vinogradov 18 ноября 2010 в 12:55

RxB wrote:
А что вы с настройками поля делать будете?

После этого уже можно спокойно лезть в админку и править настройки поля ) Их не так уж и много, на самом-то деле.
Зато, если править базу, то не нужно потом трогать Views, некоторые шаблоны и прочее, что завязано на имени поля.

Но! У меня вопрос - а почему вы хотите сделать издательство - текстовым полем? Связка по id (тот самый int!) гораздо лучше - как вариант такого использования, уже предложили таксономию.

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 ноября 2010 в 12:54

"RxB" wrote:

А что вы с настройками поля делать будете?


для способа UPDATE это не нужно - поле создается в друпале.
потом лишнее удаляется

Аватар пользователя Виктор Степаньков ака RxB Виктор Степаньк... 18 ноября 2010 в 13:02

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
для способа UPDATE это не нужно - поле создается в друпале.

Имеются ввиду специфичные настройки поля.
Я, конечно, понимаю, что насырую править в БД, убивать котят и прочее прочее прочее, это круто.
Но откуда вы знаете какой функционал ещё имеется на сайте?
Работая в ТП патруля я уже столько всего интересного насмотрелся, когда виноват в первую очередь хостинг, а не вредные советы, что желания делать в обход стандартных механизмов никакого.

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 ноября 2010 в 13:15

"RxB" wrote:
Имеются ввиду специфичные настройки поля.

"RxB" wrote:
Но откуда вы знаете какой функционал ещё имеется на сайте?

Приведите, пожалуйста, пример, какие настройки / функционал.

В запросе логика такая:
1. Создается поле нужного типа. (текстовая строка)
2. выполняется запрос mysql
3. удаляется ненужное поле.

Я сделал импорт 200к нод с 4 видами таксономии и 3 типа материала, некоторые поля дублировались (использовались в разных типах материала) из простого дампа mysql и структуру базы друпала успел выучить.

Поэтому могу на Ваш вопрос могу с уверенностью ответить, что это ничего не повредит, и никаких таких "специфических" настроек поля нет, если они задаются вручную в друпале, а данные они и есть данные, это не настройки.
Правда, как заметили выше, новое поле может выпасть из views и тем, но от Вашего решения оно отличается только тем, что вместо 200 запросов будет один к базе. Попробуйте лог sql своего запроса сделать и сами поймете, что там делается.

Аватар пользователя Виктор Степаньков ака RxB Виктор Степаньк... 18 ноября 2010 в 13:24

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:

Приведите, пожалуйста, пример, какие настройки / функционал.

В запросе логика такая:
1. Создается поле нужного типа. (текстовая строка)
2. выполняется запрос mysql
3. удаляется ненужное поле.


Я прекрасно умею читать, даже SQL.

Просто у вас всё вышло, всё круто, всё чотко, но вы можете гарантировать что у автора выйдет так же?
Может у него это вообще общее поле для трёх типов материалов или ещё что-нить хуже?

Для 200 000 нод может и я бы делал через скуль, но 200 нод, извините, я дольше буду туда идти, через выполню пересохранение.

Всегда когда не уверен или не можешь гарантировать правильную работу, нужно делать через API.
Иначе потом появляется:
-Пишет непонятное н/д (скуль-мастер забыл/не знал про ревизии)
-Таксономия двоится (разработчик модуля был знатный извращенец, про ревизии тоже не слышал, в итоге в hook_view() выводил термины по nid)
-Все ссылки оборачиваются в noindex (разработчик прям в index.php прописал регулярку для оборачивания ссылок)
и ещё миллион подобных случаев.

Был бы автор в себе уверен, он бы сделал это сам и не спрашивал совета

Аватар пользователя Valeratal Valeratal 18 ноября 2010 в 13:33

издательство термином
почему бы и нет, имхо было бы удобнее

только это уже другое решение, я так понимаю

(можно применить VBO)

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 ноября 2010 в 13:39

"RxB" wrote:
Может у него это вообще общее поле для трёх типов материалов или ещё что-нить хуже?

Ну на этот случай друпал таблицу создает по имени поля content_field_[название поля], запрос не станет сложнее, я про это писал.

Самый муторный случай - картинки в imagefield засовывать с множественным полем - там одним запросом тяжело.

Тем не менее, согласен с Вами, что если то, что предложили не совсем понятно, и поэтому страшно, то Ваш вариант безопаснее.

Аватар пользователя andribas@drupal.org andribas@drupal.org 18 ноября 2010 в 14:44

"Valeratal" wrote:
только это уже другое решение, я так понимаю

(можно применить VBO)

я бы сделал на mysql:

создаете словарь в друпале, привязываете его к материалу.
берете его vid из vocabulary = MYVID (подставлять значение)
берете максимальный tid из term_data = MYTID (подставлять значение)
потом добавляете термины:
если id издателя что-то вроде auto_increment, т.е. 1,2,3... то вставляете так:

INSERT INTO term_data (tid,vid,name,description,weight) IGNORE
  SELECT MYTID + field_publisher_id,MYVID, field_publisher_id, '', 0 FROM content_type_[TYPE OF book]
INSERT INTO term_hierarchy (tid,parent) IGNORE
  SELECT MYTID + field_publisher_id,0 FROM content_type_[TYPE OF book]

IGNORE - для дубликатов.

Потом добавляете термины к нодам:

INSERT INTO term_node (nid,vid,tid)
  SELECT nid,MYVID,MYTID + field_publisher_id FROM content_type_[type_of_book]

Если id издателей не по порядку идет, то лучше сделать вспомогательную таблицу с новыми id (начиная с MYTID+1) и старыми

CREATE TABLE map (
 newid UNSIGNED INT NOT NULL DEFAULT '0' AUTO_INCREMENT,
 id  UNSIGNED INT NOT NULL DEFAULT '0',
 PRIMARY KEY (newid),
 UNIQUE (id)
);
INSERT INTO map (id) IGNORE SELECT field_publisher_id FROM content_type_[type_of_book] ORDER BY field_publisher_id
UPDATE map SET newid = newid + MYTID ORDER BY newid DESC

ну а дальше еще один join в запросах.
Если id издателя у Вас уже линкуется с каким-то названием, то можно потом значение в словарь терминов засунуть.
потом map удаляете.

Если что-то непонятно помогу.

шапраглка по таблицам здесь

Аватар пользователя владимирович владимирович 6 ноября 2012 в 16:52

"RxB" wrote:
Делаем новое поле текстовое, например, publishertxt, старое просто publisher к примеру
далее выполняем сниппет:

"<a href="mailto:andribas@drupal.org">andribas@drupal.org</a>" wrote:
А не проще сделать одним запросом?
Сначала добавьте поле, потом:

UPDATE content_type_книга SET field_publiser_value = field_id_value


Для 7 Друпала эти методы подходят? Мне нужно заменить существующие текстовые поля на числовые

Аватар пользователя sg85 sg85 6 ноября 2012 в 18:01

"владимирович" wrote:
Для 7 Друпала эти методы подходят? Мне нужно заменить существующие текстовые поля на числовые

1 Про SQL запрос - не совсем, логика Fields отличается от CCK, если в CCK для каждого типа материала создается отдельная таблица, то в Fields, для каждого поля отдельная таблица, кроме того, пустые данные туда не попадают, т.е. после создания таблицы нужно её заполнить, например таким запросом INSERT INTO field_data_field_2(entity_type, bundle, entity_id, revision_id, `language`, delta, field_2_value) SELECT entity_type, bundle, entity_id, revision_id, `language`, delta, field_1_value field_2_value FROM field_data_field_1;, однако такой запрос имеет ряд ограничений, так что, если не понимаете до конца, что это за хрень, то использовать прямые запросы крайне не рекомендую.

Способ от RxB, если портировать под 7рку, очень даже годен, отличается длительным(в сравнении с прямым запросом) временем обработки, потому при большом числе нод выполнять этот снипет лучше через Batch Api(или через модуль VBO, он поддерживает отработку PHP скриптов через Batch Api), однако он в разы безопаснее и надежнее.