powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Прошу помощи для старой версии FP
10 сообщений из 10, страница 1 из 1
Прошу помощи для старой версии FP
    #33976470
mikle_new
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть две таблицы. В которых есть разное количество записей. Необходимо в большую таблицу внести изменнение в поле при условии совпадени полей во второй таблице. Пытаюсь сделать что-то типа:
UPDATE dsber set dsber.Account = trans.Nomer1 where dsber.Name=trans.Name1 and dsber.Name1=trans.Name2 and dsber.Name2=trans.Name3
пишет, что обновляет только 1 запись
Если делать
select * from dsber a, trans b where a.Name=b.Name1 and a.Name1=b.Name2 and a.Name2=b.Name3
Выводит 794 записи.
Как обновить все записи, который выдает Select?
VP - 5.0
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976601
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Команда Update-SQL "научилась" использовать подзапросы только в VFP9.

Для младших версий FoxPro приведенный тобой синтаксис означает, что замена будет произведена только среди тех записей таблицы dsber для которых выполняется условие WHERE в отношении текущей записи таблицы trans . Нет перемещения по таблице trans

Решений проблемы несколько:

-) Использовать старую команду UPDATE (не путать с Update-SQL), оставленную для совместимости. Но, поскольку ее явно не рекомендуют использовать, то "мы пойдем другим путем"

-) "Тупое" сканирование записей

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SELECT trans
SET ORDER TO  0   && для оптимизации (ускорения) команды LOCATE
SELECT dsber 
SET ORDER TO  0   && для оптимизации (ускорения) команды SCAN
SCAN
	SELECT trans
	LOCATE FOR trans.Name1=dsber.Name and ;
		trans.Name2=dsber.Name2 and ;
		trans.Name3=dsber.Name3

	SELECT dsber 
	IF FOUND("trans")
		REPLACE Account WITH trans.Nomer1 
	ENDIF
ENSCAN

Ускорение команды LOCATE будет в случае наличия простых индексов по полям trans.Name1, trans.Name2 и trans.Name3. Или хотя бы по одному из них, но обладающего наибольшей селективностью (меньший процент повторяющихся значений)

-) Если общая длина полей trans.Name1+trans.Name2+trans.Name3 не превышает 120 символов (при настройке SET COLLATE TO MACHINE - это настройка по умолчанию - до 240 символов), то можно построить простой индекс

Код: plaintext
1.
2.
3.
4.
5.
6.
SELECT trans
INDEX ON Name1+Name2+Name3 TO TempIndex.idx COMPACT
SELECT dsber 
SET ORDER TO  0   && для оптимизации (ускорения) команды REPLACE 
REPLACE FOR SEEK(dsber.Name+dsber.Name2+dsber.Name3,"trans","TempIndex") ;
	Account WITH trans.Nomer1

Правда, для разовой модификации это смысла не имеет, поскольку время построения индекса будет сопоставимо со временем сканирования таблиц по предыдущему варианту.
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976630
mikle_new
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за быстрый ответ.
Действительно преобразование необходимо выполнить 1 раз.
Запустил Ваш код, однако выдается ошибка:
Nesting error (Error 96)

One of these situations has been encountered:

· A DO is present without a matching ENDDO or vice versa
· A SCAN is present without a matching ENDSCAN or vice versa
· A FOR is present without a matching ENDFOR or vice versa
· A LOOP or EXIT clause is present outside the DO WHILE ... ENDDO, FOR ... ENDFOR, or SCAN ... ENDSCAN commands.

Видимо не закрыт FOR? Но не могу понять где он должен быть закрыт.
Прошу прощения за свою бестолковость - раньше с FoxPro не сталкивался.
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976635
mikle_new
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, опечатку в Вашем коде (ENDSCAN) я подправил, но это не помогло. ;o(
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976694
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mikle_newДа, опечатку в Вашем коде (ENDSCAN) я подправил, но это не помогло. ;o(
Почему не помогло? Ошибка 96 именно с этим и связана. Есть открывающая команда, но нет закрывающей.

Возможно, ты еще что не так записал в команде LOCATE FOR.

Для FoxPro символ точки с запятой ";" - это символ переноса команды. Т.е. сигнал о том, что команда продолжается на следующей строке.

На этапе компиляции никакого сообщения об ошибке не возникает? Если возникает, то на какой строке?
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976699
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя неудачное название таблицы "trans". Совпадает с ключевым словом FoxPro "TRANSFORM". В принципе, на работу это влиять не должно, но... Попробуй изменить алиас таблицы при открытии

Код: plaintext
USE Trans.dbf IN  0  ALIAS MyTrans

Соответственно, внеси исправления в код программы.
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976707
mikle_new
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Почитал Help, понял, что нужно Ваш код оформить через программку. Написал программу:
SET DEFAULT TO "c:\program files\work"
USE "c:\program files\work\trans.dbf"
USE "c:\program files\work\dsber.dbf" in 0
SELECT trans
SET ORDER TO 0
SELECT dsber
SET ORDER TO 0
SCAN
SELECT trans
LOCATE FOR trans.Name1=dsber.Name and ;
trans.Name2=dsber.Name1 and ;
trans.Name3=dsber.Name2
SELECT dsber
IF FOUND("trans")
REPLACE Account WITH trans.Nomer1
ENDIF
ENDSCAN
Однако при выполнении в точку где Replace программа не попадает. В чем может быть дело?
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976714
mikle_new
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подправил Alias и код. Ошибок при компиляции не выдает. Однако на строку с Replase не попадает. Интересно, что после выполнение Locate в переменной MyTrans.Name по дебагеру видно только пустое значение. може быть проблема в услоавиях для Loсate?
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976723
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя поля, которые ты сравниваешь имеют одинаковую длину? Размерность полей какая?

Дело в том, что логика сравнения символьных полей в команде Select-SQL несколько отличается от логики сравнения символьных полей в "обычных" командах. Как правило, это проявляется именно в случае сравнения полей разной длинны. Подробнее читай описание настроек SET EXACT (для обычных команд) и SET ANSI (для Select-SQL)

Ну, например, если поле trans.Name1 имеет размерность C(20), а поле dsber.Name имеет размерность C(25), то сравнение

trans.Name1 = dsber.Name

в случае, если содержимое отличается только концевыми пробелами при настройках по умолчанию, в команде Select-SQL вернет .T., а в обычных командах .F.

Измени команду LOCATE следующим образом:

Код: plaintext
1.
2.
3.
LOCATE FOR trans.Name1=RTRIM(dsber.Name) and ;
	trans.Name2=RTRIM(dsber.Name2) and ;
	trans.Name3=RTRIM(dsber.Name3)

В таком синтаксисе размерность полей не должна влиять на результат.

То, что после команды LOCATE в таблице Trans содержимое полей пустое, означает, что поиск прошел неудачно и указатель записи встал в положение EOF()=.T. Т.е. встал на некую фиктивную запись, все поля которой имеют пустое значениею
...
Рейтинг: 0 / 0
Прошу помощи для старой версии FP
    #33976730
mikle_new
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Действительно именно в этом была проблема. Большое спасибо за реальную помощь.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Прошу помощи для старой версии FP
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]