MySQL запрос. Синтаксическая ошибка.

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
Есть код
PHP:
public OnClientDisconnect(client)
{ 
	if (db == INVALID_HANDLE)
	{
		new String:Error[256];
		LogError("Fail connect: %s", Error);
	}
	else if(Player[PlayerJoin][client] == 1 && !IsFakeClient(client)) 
	{ 
		CheckNewNix(client);
		CheckstVIP(client);
		Player[PlayerJoin][client] = 0;
		decl String:sAuth[64], String:pName[150], String:query[2048]; 
		GetClientName(client, sAuth, sizeof(sAuth) - 1); 
		SQL_EscapeString(db, sAuth, pName, sizeof(pName) - 1); 
		GetClientAuthString(client, sAuth, sizeof(sAuth) - 1); 
		FormatEx(query, sizeof(query), 
		"INSERT INTO dp_users (Steam, Nick, Kills, Deaths, Level, EXP, Credits, BanValue, Rating) VALUES ('%s', '%N', %d, %d, %d, %d, %d, %d, %d) ON DUPLICATE KEY UPDATE Steam = '%s', Nick = '%N', Kills = %d, Deaths = %d, Level = %d, EXP = %d, Credits = %d, BanValue = %d, Rating = %d",
		sAuth,
		client,
		Player[pKills][client],
		Player[pDeaths][client],
		Player[pLevel][client],
		Player[pEXP][client],
		Player[pCredit][client],
		Player[pBanValue][client],
		Player[Rating][client],
		sAuth,
		client,
		Player[pKills][client],
		Player[pDeaths][client],
		Player[pLevel][client],
		Player[pEXP][client],
		Player[pCredit][client],
		Player[pBanValue][client],
		Player[Rating][client]);

		SQL_TQuery(db, SQL_SelectPlayerCallback, query);
	} 
}
Периодически выдаёт ошибку
PHP:
Ошибка подключения к базе данных (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 's', 10, 17, 1, 0, 10, 0, 27) ON DUPLICATE KEY UPDATE Steam = 'STEAM_1:1:1234567' at line 1)

Что не так с запросом, или как решить эту проблему?
 

ykpon

Владыка
Сообщения
675
Реакции
401
Есть код
PHP:
public OnClientDisconnect(client)
{ 
	if (db == INVALID_HANDLE)
	{
		new String:Error[256];
		LogError("Fail connect: %s", Error);
	}
	else if(Player[PlayerJoin][client] == 1 && !IsFakeClient(client)) 
	{ 
		CheckNewNix(client);
		CheckstVIP(client);
		Player[PlayerJoin][client] = 0;
		decl String:sAuth[64], String:pName[150], String:query[2048]; 
		GetClientName(client, sAuth, sizeof(sAuth) - 1); 
		SQL_EscapeString(db, sAuth, pName, sizeof(pName) - 1); 
		GetClientAuthString(client, sAuth, sizeof(sAuth) - 1); 
		FormatEx(query, sizeof(query), 
		"INSERT INTO dp_users (Steam, Nick, Kills, Deaths, Level, EXP, Credits, BanValue, Rating) VALUES ('%s', '%N', %d, %d, %d, %d, %d, %d, %d) ON DUPLICATE KEY UPDATE Steam = '%s', Nick = '%N', Kills = %d, Deaths = %d, Level = %d, EXP = %d, Credits = %d, BanValue = %d, Rating = %d",
		sAuth,
		client,
		Player[pKills][client],
		Player[pDeaths][client],
		Player[pLevel][client],
		Player[pEXP][client],
		Player[pCredit][client],
		Player[pBanValue][client],
		Player[Rating][client],
		sAuth,
		client,
		Player[pKills][client],
		Player[pDeaths][client],
		Player[pLevel][client],
		Player[pEXP][client],
		Player[pCredit][client],
		Player[pBanValue][client],
		Player[Rating][client]);

		SQL_TQuery(db, SQL_SelectPlayerCallback, query);
	} 
}
Периодически выдаёт ошибку
PHP:
Ошибка подключения к базе данных (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 's', 10, 17, 1, 0, 10, 0, 27) ON DUPLICATE KEY UPDATE Steam = 'STEAM_1:1:1234567' at line 1)

Что не так с запросом, или как решить эту проблему?

Открыть базу данных и удалить дубликат.
Либо добавить колонку 'id' и установить ее как "auto_increment".
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
ykpon, не то) Плохое решение) И я не делал id. В этом нет нужды.

В общем, проблема, как я понял, в том, что в нике может быть спецсимвол типа кавычки, из-за этого весь запрос рушится. Я думал, что SQL_EscapeString решает эту проблему, но оно не решило проблему. Есть ли еще варианты решения?
 

ykpon

Владыка
Сообщения
675
Реакции
401
ykpon, не то) Плохое решение) И я не делал id. В этом нет нужды.

В общем, проблема, как я понял, в том, что в нике может быть спецсимвол типа кавычки, из-за этого весь запрос рушится. Я думал, что SQL_EscapeString решает эту проблему, но оно не решило проблему. Есть ли еще варианты решения?

Может что то не передается в запрос? Включай дебаг. Вместе с запросом выводи данные, которые передаются.
 

Саша Шеин

Кому костылей?
Сообщения
1,697
Реакции
621
Заменяй спец символ на чёнить другое. Я так делаю в RPG и в Army Ranks вроде так тоже сделано.
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
ykpon, я, вроде, предоставил код. Смотри код, всё передаётся.

Заменяй спец символ на чёнить другое. Я так делаю в RPG и в Army Ranks вроде так тоже сделано.
Хорошая идея, попробую. Еще варианты есть? :D
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #7
Primo, предже всего сделай LogMessage(query); чтобы увидеть что в запросе не так.
На sql кажется ON DUPLICATE KEY UPDATE у меня не работало и выдавало ошибку как у тебя...
По поводу
SQL_EscapeString(db, sAuth, pName, sizeof(pName) - 1);
Вообще мистическая ф-я. То всё норм, то в ручную нужно экранировать символы.
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
R1KO, я с 100% уверенностью скажу, что это из-за ' в нике. У чувака ник 'BenQ, а в ошибку вывело всё, что после ', то бишь BenQ, 0, 0, 0 ON DUPLICATE KEY UPDATE SET...... Указывая на то, что с ника пошел ошибочный синтаксис.
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #9
Primo, пробуй ReplaceString "'" to "" или "\'" (или "\\'")
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
R1KO, Оффтоп
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #11
PHP:
static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params)
{
	IDatabase *db = NULL;
	HandleError err;

	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
		!= HandleError_None)
	{
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
	}

	char *input, *output;
	size_t maxlength = (size_t)params[4];
	pContext->LocalToString(params[2], &input);
	pContext->LocalToString(params[3], &output);

	size_t written;
	bool s = db->QuoteString(input, output, maxlength, &written);

	cell_t *addr;
	pContext->LocalToPhysAddr(params[5], &addr);
	*addr = (cell_t)written;

	return s ? 1 : 0;
}

/**
		 * Quotes a string for insertion into a query.
		 *
		 * @param str			Source string.
		 * @param buffer		Buffer to store new string (should not overlap source string).
		 * @param maxlen		Maximum length of the output buffer.
		 * @param newSize		Pointer to store the output size.
		 * @return				True on success, false if the output buffer is not big enough.
		 *						If not big enough, the required buffer size is passed through
		 *						newSize.
		 */
		virtual bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) =0;
...
mysql_real_escape_string(m_mysql, buffer, str, size);
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
R1KO,
Notes:
This is a backwards compatibility stock. You should use SQL_EscapeString() instead, as this function will probably be deprecated in SourceMod 1.1.
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #13
Primo, это только в inc SQL_EscapeString, на самом деле это старая SQL_QuoteString. Я скинул исходы sm
 

ykpon

Владыка
Сообщения
675
Реакции
401
ykpon, я, вроде, предоставил код. Смотри код, всё передаётся.

Ничего не видно, что у тебя передается.
Одно дело, что ты в скрипте прописал, другое, что передается на самом деле, в запросе.
В консоль выводи содержимое запроса.
Это элементарный вопрос отладки.
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
ykpon, ну, я, конечно, понимаю, что тебе нужно больше информации, но она предоставлена.
Давай рассуждать логически:
C-подобный:
        Player[pKills][client], 
        Player[pDeaths][client], 
        Player[pLevel][client], 
        Player[pEXP][client], 
        Player[pCredit][client], 
        Player[pBanValue][client], 
        Player[Rating][client],
Это целочисленные переменные, они в любом случае будут иметь какое-то значение, пусть даже 0.

C-подобный:
        GetClientAuthString(client, sAuth, sizeof(sAuth) - 1);
sAuth. Из ошибки видно, что STEAMID получен!
Ну а client что, получить ник, зная индекс, плёвое дело. Из ошибки ты видел, что ник получен.

Вопрос, что тебя не устраивает? Запрос прописан, что я передаю в запросе тоже написано.

А, ну для описания решения проблемы: я, дурак, делаю SQL_EscapeString, да вот в запросе pName не использую, моя невнимательность.
 

Mr_Incognito

Участник
Сообщения
194
Реакции
14
Подскажите как исправить?
[levelsranks.smx] SQL_TransactionFailure (1): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE `SteamID` = 'STEAM_1:0:245116005'' at line 1 (1)
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
полностью запрос весь покажи
Подскажите как исправить?
[levelsranks.smx] SQL_TransactionFailure (1): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE `SteamID` = 'STEAM_1:0:245116005'' at line 1 (1)
 

Mr_Incognito

Участник
Сообщения
194
Реакции
14

Вложения

  • levelsranks.sp
    4 КБ · Просмотры: 2
Последнее редактирование:
Сверху Снизу