英文:
Stored Procedure WITH SINGLE QUOTES
问题
你遇到的问题是在SQL查询字符串中,CONCAT
函数没有正确添加单引号。要解决这个问题,你需要在CONCAT
函数的参数之间添加单引号。下面是修复后的SQL查询字符串:
CONCAT(`cv`.`name`, ' ', `cv`.`value`) AS `characteristic`,
这样修改后,查询字符串中会正确添加空格,并且cv.name
和cv.value
之间将有单引号包围,不再引发语法错误。
请注意,修复后的查询字符串应该替代原始的查询字符串中的相应部分。
英文:
Hi i have the next SP:
CREATE DEFINER=`admin`@`%` PROCEDURE `get_products_id`(IN column_name VARCHAR(50))
BEGIN
SET @column_name = column_name;
SET @query = CONCAT('SELECT
`p`.`id` AS `id`,
`p`.`image` AS `image`,
`p`.`globalClasification` AS `globalClasification`,
`p`.`itemId` AS `itemId`,
`p`.`code` AS `code`,
`p`.`providerCode` AS `providerCode`,
`p`.`description` AS `description`,
`p`.`unspscCode` AS `unspscCode`,
`p`.`productServiceKey` AS `productServiceKey`,
`p`.`unit` AS `unit`,
`p`.`keywords` AS `keywords`,
`p`.`commonName` AS `commonName`,
`p`.`barCode` AS `barCode`,
`p`.`promo` AS `promo`,
`p`.`pdi` AS `pdi`,
`p`.`deleted` AS `deleted`,
`p`.`distribution` AS `distribution`,
`p`.`productTypeId` AS `productTypeId`,
`pt`.`name` AS `productTypeName`,
`p`.`brandId` AS `brandId`,
`p`.`existencia` AS `existencia`,
`p`.`existenciaUpdatedAt` AS `stockUpdatedAt`,'
'`p`.`', @column_name, '` AS `column`, '
'`b`.`name` AS `brandName`,
`c`.`id` AS `categoryId`,
`c`.`name` AS `categoryName`,
`c`.`parentId` AS `parentId`,
`c`.`pdi` AS `categoryPdi`,
CONCAT(`cv`.`name`, ' ', `cv`.`value`) AS `characteristic`,
`cv`.`name` AS `characteristicName`,
`cv`.`value` AS `characteristicValue`,
`cv`.`filter` AS `cvfilter`,
`p`.`obsoleto` AS `obsoleto`
FROM
(((((`risoul_test`.`products` `p`
JOIN `risoul_test`.`categoryproduct` `cp` ON ((`cp`.`productId` = `p`.`id`)))
JOIN `risoul_test`.`categories` `c` ON ((`c`.`id` = `cp`.`categoryId`)))
JOIN `risoul_test`.`characteristicValues` `cv` ON ((`p`.`id` = `cv`.`productId`)))
JOIN `risoul_test`.`brands` `b` ON ((`b`.`id` = `p`.`brandId`)))
JOIN `risoul_test`.`productTypes` `pt` ON ((`pt`.`id` = `p`.`productTypeId`)))
WHERE `p`.`deleted` = 0');
SELECT @query;
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
I get an error on the following line
CONCAT(`cv`.`name`, ' ', `cv`.`value`) AS `characteristic`,
And the response is the next: Error Code: 1064 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 ', cv
.value
) AS characteristic
, cv
.name
AS characteristicName
, `c' at line 28
I do a log and the result i get is the next:
'SELECT
`p`.`id` AS `id`,
`p`.`image` AS `image`,
`p`.`globalClasification` AS `globalClasification`,
`p`.`itemId` AS `itemId`,
`p`.`code` AS `code`,
`p`.`providerCode` AS `providerCode`,
`p`.`description` AS `description`,
`p`.`unspscCode` AS `unspscCode`,
`p`.`productServiceKey` AS `productServiceKey`,
`p`.`unit` AS `unit`,
`p`.`keywords` AS `keywords`,
`p`.`commonName` AS `commonName`,
`p`.`barCode` AS `barCode`,
`p`.`promo` AS `promo`,
`p`.`pdi` AS `pdi`,
`p`.`deleted` AS `deleted`,
`p`.`distribution` AS `distribution`,
`p`.`productTypeId` AS `productTypeId`,
`pt`.`name` AS `productTypeName`,
`p`.`brandId` AS `brandId`,
`p`.`existencia` AS `existencia`,
`p`.`existenciaUpdatedAt` AS `stockUpdatedAt`,`p`.`poPrueba` AS `column`, `b`.`name` AS `brandName`,
`c`.`id` AS `categoryId`,
`c`.`name` AS `categoryName`,
`c`.`parentId` AS `parentId`,
`c`.`pdi` AS `categoryPdi`,
CONCAT(`cv`.`name`, , `cv`.`value`) AS `characteristic`,
`cv`.`name` AS `characteristicName`,
`cv`.`value` AS `characteristicValue`,
`cv`.`filter` AS `cvfilter`,
`p`.`obsoleto` AS `obsoleto`
FROM
(((((`risoul_test`.`products` `p`
JOIN `risoul_test`.`categoryproduct` `cp` ON ((`cp`.`productId` = `p`.`id`)))
JOIN `risoul_test`.`categories` `c` ON ((`c`.`id` = `cp`.`categoryId`)))
JOIN `risoul_test`.`characteristicValues` `cv` ON ((`p`.`id` = `cv`.`productId`)))
JOIN `risoul_test`.`brands` `b` ON ((`b`.`id` = `p`.`brandId`)))
JOIN `risoul_test`.`productTypes` `pt` ON ((`pt`.`id` = `p`.`productTypeId`)))
WHERE `p`.`deleted` = 0'
It doesn't seem to add the single quotes.
What do i have to change to make it work?
答案1
得分: 2
问题在于您正在创建一个单引号字符串,该字符串本身包含您希望成为文字单引号字符的单引号。但您希望成为文字的单引号实际上终止了这个单引号字符串。
在MySQL中了解字符串文字的内容:
https://dev.mysql.com/doc/refman/8.0/en/string-literals.html
相邻放置的带引号的字符串将连接成一个字符串。以下几行是等效的:
'a string' 'a' ' ' 'string'
因此,在您的情况下,您希望作为CONCAT()表达式一部分的单引号最终将整个查询字符串分割成了多个部分,但这没关系,因为MySQL的字符串文字语法允许这样做。
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, ' ', `cv`.`value`) AS `characteristic`,
^ ^
终结第一部分 开始第二部分
如果您希望使用文字引号字符,也可以在同一手册页面中找到相关信息:
有几种方法可以在字符串中包含引号字符:
在带有单引号引号的字符串中,' 可以写作 ''。
在带有双引号引号的字符串中," 可以写作 ""。
在引号字符之前加上转义字符 ()。
在双引号引号中的 ' 无需特殊处理,也无需加倍或转义。同样,带有单引号引号的 " 无需特殊处理。
因此,您可以以以下方式之一编写它:
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, '' '', `cv`.`value`) AS `characteristic`,
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, \\' \\', `cv`.`value`) AS `characteristic`,
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, "" "", `cv`.`value`) AS `characteristic`,
我建议避免使用最后一个解决方案,因为"
的含义可能会根据sql_mode
配置而变为标识符分隔符。
英文:
The problem is that you are making a single-quoted string, which itself contains single-quotes that you expect to be literal single-quote characters. But the single-quote you want to be literal end up terminating the single-quoted string.
Read about string literals in MySQL:
https://dev.mysql.com/doc/refman/8.0/en/string-literals.html
> Quoted strings placed next to each other are concatenated to a single string. The following lines are equivalent:
>
> 'a string'
> 'a' ' ' 'string'
So in your case, the single-quotes you want to be part of your CONCAT() expression end up turning the whole query string into parts, but that's okay because MySQL's string literal syntax allows it.
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, ' ', `cv`.`value`) AS `characteristic`,
^ ^
end first part start second part
What you need to do if you want literal quote characters is also documented in the same manual page:
> There are several ways to include quote characters within a string:
>
> - ' inside a string quoted with ' may be written as ''.
>
> - " inside a string quoted with " may be written as "".
>
> - Precede the quote character by an escape character ().
>
> - A ' inside a string quoted with " needs no special treatment and need not be doubled or escaped. In the same way, " inside a string quoted with ' needs no special treatment.
You could therefore write it in one of these ways:
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, '' '', `cv`.`value`) AS `characteristic`,
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, \' \', `cv`.`value`) AS `characteristic`,
SET @query = CONCAT('SELECT ...
CONCAT(`cv`.`name`, " ", `cv`.`value`) AS `characteristic`,
I would recommend avoiding the last solution because the meaning of "
can change to an identifier delimiter depending on the sql_mode
configuration.
答案2
得分: 2
Bill已经在流程中解决了这个问题。
通过去除不必要的反引号和括号,你可以使代码更易于阅读和维护。反引号只在列名中包含特殊字符时才是必需的(无论如何,你本不应该有这种特殊字符)。
你也可以直接在CONCAT中使用参数,不需要将其分配给用户定义的变量。
CREATE DEFINER=`admin`@`%` PROCEDURE get_products_id(
in_column_name VARCHAR(50)
)
BEGIN
SET @query = CONCAT('SELECT
p.id AS id,
p.image AS image,
p.globalClasification AS globalClasification,
p.itemId AS itemId,
p.code AS code,
p.providerCode AS providerCode,
p.description AS description,
p.unspscCode AS unspscCode,
p.productServiceKey AS productServiceKey,
p.unit AS unit,
p.keywords AS keywords,
p.commonName AS commonName,
p.barCode AS barCode,
p.promo AS promo,
p.pdi AS pdi,
p.deleted AS deleted,
p.distribution AS distribution,
p.productTypeId AS productTypeId,
pt.name AS productTypeName,
p.brandId AS brandId,
p.existencia AS existencia,
p.existenciaUpdatedAt AS stockUpdatedAt,
', in_column_name, ' AS ''colum'',
b.name AS brandName,
c.id AS categoryId,
c.name AS categoryName,
c.parentId AS parentId,
c.pdi AS categoryPdi,
CONCAT(cv.name, '' '', cv.value) AS characteristic,
cv.name AS characteristicName,
cv.value AS characteristicValue,
cv.filter AS cvfilter,
p.obsoleto AS obsoleto
FROM
risoul_test.products p
JOIN risoul_test.categoryproduct cp ON cp.productId = p.id
JOIN risoul_test.categories c ON c.id = cp.categoryId
JOIN risoul_test.characteristicValues cv ON p.id = cv.productId
JOIN risoul_test.brands b ON b.id = p.brandId
JOIN risoul_test.productTypes pt ON pt.id = p.productTypeId
WHERE p.deleted = 0');
SELECT @query;
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
(注意:代码中的反引号已被移除,并保留了你的参数in_column_name的用法。)
英文:
Bill already addressed the issue in the procedure.
You can make the code easier to read and maintain by removing unnecessary backticks and parentheses. Backticks are only required if you have special characters in your column names (which you should not have anyways).
You can also use the parameter in your CONCAT directly, no need to assign it to a user defined variable.
CREATE DEFINER=`admin`@`%` PROCEDURE get_products_id(
in_column_name VARCHAR(50)
)
BEGIN
SET @query = CONCAT('SELECT
p.id AS id,
p.image AS image,
p.globalClasification AS globalClasification,
p.itemId AS itemId,
p.code AS code,
p.providerCode AS providerCode,
p.description AS description,
p.unspscCode AS unspscCode,
p.productServiceKey AS productServiceKey,
p.unit AS unit,
p.keywords AS keywords,
p.commonName AS commonName,
p.barCode AS barCode,
p.promo AS promo,
p.pdi AS pdi,
p.deleted AS deleted,
p.distribution AS distribution,
p.productTypeId AS productTypeId,
pt.name AS productTypeName,
p.brandId AS brandId,
p.existencia AS existencia,
p.existenciaUpdatedAt AS stockUpdatedAt,
p.', in_column_name, ' AS ''colum'',
b.name AS brandName,
c.id AS categoryId,
c.name AS categoryName,
c.parentId AS parentId,
c.pdi AS categoryPdi,
CONCAT(cv.name, '' '', cv.value) AS characteristic,
cv.name AS characteristicName,
cv.value AS characteristicValue,
cv.filter AS cvfilter,
p.obsoleto AS obsoleto
FROM
risoul_test.products p
JOIN risoul_test.categoryproduct cp ON cp.productId = p.id
JOIN risoul_test.categories c ON c.id = cp.categoryId
JOIN risoul_test.characteristicValues cv ON p.id = cv.productId
JOIN risoul_test.brands b ON b.id = p.brandId
JOIN risoul_test.productTypes pt ON pt.id = p.productTypeId
WHERE p.deleted = 0');
SELECT @query;
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论