在mysql中反序列化和序列化数据

时间:2020-07-19 13:10:59

标签: php mysql sql

有什么方法可以在不使用php或仅使用SQL语言的情况下反序列化和序列化mysql中的数据?

致力于woocommerce插件,该插件存储在数据库中序列化的购物车商品。 目的是对购物车表进行查询并获取购物车项目,然后将结果发送到API。 购物车项目以序列化数据的形式存储在表中,例如:

a:1:{s:4:"cart";a:2:{s:32:"76dc611d6ebaafc66cc0879c71b5db5c";a:11:{s:3:"key";s:32:"76dc611d6ebaafc66cc0879c71b5db5c";s:10:"product_id";i:128;s:12:"variation_id";i:0;s:9:"variation";a:0:{}s:8:"quantity";i:1;s:9:"data_hash";s:32:"b5c1d5ca8bae6d4896cf1807cdf763f0";s:13:"line_tax_data";a:2:{s:8:"subtotal";a:0:{}s:5:"total";a:0:{}}s:13:"line_subtotal";d:500;s:17:"line_subtotal_tax";i:0;s:10:"line_total";d:500;s:8:"line_tax";i:0;}s:32:"65ded5353c5ee48d0b7d48c591b8f430";a:6:{s:3:"key";s:32:"65ded5353c5ee48d0b7d48c591b8f430";s:10:"product_id";i:132;s:12:"variation_id";i:0;s:9:"variation";a:0:{}s:8:"quantity";i:1;s:9:"data_hash";s:32:"b5c1d5ca8bae6d4896cf1807cdf763f0";}}}

在在线工具中反序列化之后,我得到了这样的结构:

Array
  (
   [cart] => Array
    (
        [76dc611d6ebaafc66cc0879c71b5db5c] => Array
            (
                [key] => 76dc611d6ebaafc66cc0879c71b5db5c
                [product_id] => 128
                [variation_id] => 0
                [variation] => Array
                    (
                    )

                [quantity] => 1
                [data_hash] => b5c1d5ca8bae6d4896cf1807cdf763f0
                [line_tax_data] => Array
                    (
                        [subtotal] => Array
                            (
                            )

                        [total] => Array
                            (
                            )

                    )

                [line_subtotal] => 500
                [line_subtotal_tax] => 0
                [line_total] => 500
                [line_tax] => 0
            )

        [65ded5353c5ee48d0b7d48c591b8f430] => Array
            (
                [key] => 65ded5353c5ee48d0b7d48c591b8f430
                [product_id] => 132
                [variation_id] => 0
                [variation] => Array
                    (
                    )

                [quantity] => 1
                [data_hash] => b5c1d5ca8bae6d4896cf1807cdf763f0
            )

      )

  )

需要访问此对象的每个属性,并将其存储在列中,然后将查询结果发送到API。

如何用SQL语言反序列化这些数据?

2 个答案:

答案 0 :(得分:2)

我一直在为一个类似的问题而苦苦挣扎:从表 wp_postmeta 反序列化和序列化数据,对它的某些部分进行搜索和替换(我正在翻译 WooCommerce 站点,我更愿意在 MySQL 中完成这一切) ,而不是使用 PHP)。就我而言,搜索和替换总是发生在第四个 s 元素上。我为此开发了一个程序。它可能不适合您的确切用例,但可能足以满足您的需求:

CREATE DEFINER=`strompf`@`localhost` PROCEDURE `replace_serial`(
        in table_name_in            tinytext,   # Source table name
        in col_serial_data_src_in   tinytext,   # Column with source serialised data
        in col_serial_data_dst_in   tinytext,   # Column with destination serialised data
        in col_src_in               tinytext,   # Column with source text strings
        in col_dst_in               tinytext    # Column with desination text string
    )
BEGIN
#
# Find-and-replace in element s4 within serialised content
################################################################################
#
# * This sproc "replace_serial" needs as input pointers to a table 
#   ("pointer table") with the following columns:
#   * Column with the source serialised data
#   * Column for storing the updated serialised data
#   * Column with find-string
#   * Column with replace-strings
# * It can be any table: The arguments for replace_serial() contains the name
#   of this table and the names of those four columns
# * Internally, data from this input-table is copied to temporary table 
#   "serial_tmp"
# * The designated serialised data is decomposed into several fields (again,
#   in table "serial_tmp") - Currently, this sproc only works for serialised 
#   data with 1 a-element, followed by 6 s-elements. This sproc has not been 
#   tested with other configurations
# * Find-and-replace is only performed on element s4 (=the 4th s-element)
# * Subsequently, the new length of s4 is calculated, and the serialised string
#   is written to the designated column in the "pointer table"
# * Subsequently, it's up to the programmer to process the resulting data in
#   the pointer table
# * This approach with a "pointer table" works really well: Easy to grasp,
#   flexible and easy to debug. It's especially handy for debugging or further
#   processing that the output is in a separate column from the input.
# * Copyright Jeroen Strompf - De Vliegende Brigade - 2021.03.09
#
#
# History
########################################
#
# * 2021.03.09: Created, tested and pushed to "bal_dwh_org"
#
#
################################################################################
# Define working table "serial_tmp"
################################################################################
#
drop table if exists 
    serial_tmp;
create temporary table
    serial_tmp
    (
        serial_data_src     varchar(255)    comment "Actual serialised data",   
        serial_data_dst     varchar(255)    comment "Resulting serialised data. This is a separate field, to make debugging easier",
        find_string         varchar(255)    comment "String to be found within serial_data_src",
        replace_string      varchar(255)    comment "Replacement string for within serial_data_src, resulting in serial_data_dst",

        a_len           smallint,
        a_string        varchar(255)    comment "The string within the accolade",
        s1              varchar(255)    comment "Complete s-part, including length statement and string",
        s2              varchar(255),
        s3              varchar(255),
        s4              varchar(255)    comment "Complete s4-string",
        s4_len_src      smallint        comment "Original length of s4",
        s4_string_src   varchar(255)    comment "Original s4 string",
        s4_len_dst      smallint        comment "New length",
        s4_string_dst   varchar(255)    comment "New string",
        s5              varchar(255),
        s6              varchar(255)
    );


################################################################################
# Copy working data to working table
################################################################################
#
set @ddl=concat
(
    "insert into serial_tmp 
    (
        serial_data_src,
        find_string,
        replace_string
    )
    select ",
        col_serial_data_src_in, ", ",
        col_src_in, ", ",
        col_dst_in, " ",
    "from ",
        table_name_in, ";"
);

prepare stmt from @ddl;
execute stmt;
deallocate prepare stmt;


################################################################################
# Decompose serialsed data
################################################################################
#
# Leading a-field
########################################
#
update
    serial_tmp
set
    a_len       = substring_index(substring_index(serial_data_src, ":", 2), ":", -1),
    a_string    = substring_index(substring_index(serial_data_src, "}",1), "{", -1);


# Complete s-fields
########################################
#
update
    serial_tmp
set
    s1 = substring_index(a_string, ";", 1),
    s2 = substring_index(substring_index(a_string, ";", 2), ";", -1),
    s3 = substring_index(substring_index(a_string, ";", 3), ";", -1),
    s4 = substring_index(substring_index(a_string, ";", 4), ";", -1),
    s5 = substring_index(substring_index(a_string, ";", 5), ";", -1),
    s6 = substring_index(substring_index(a_string, ";", 6), ";", -1);


# Further decompose s4
########################################
#
update
    serial_tmp
set
    s4_len_src      = substring_index(substring_index(s4, ":", 2), ":", -1),
    s4_string_src   = substring_index(substring_index(s4, '"', 2), '"', -1);


################################################################################
# Find-and-replace
################################################################################
#
# Finally! The heart of the matter
#
update
    serial_tmp
set
    s4_string_dst   =   replace(s4_string_src, find_string, replace_string),
    s4_len_dst      =   length(s4_string_dst);


################################################################################
# Reassemble
################################################################################
#
update
    serial_tmp
set
    serial_data_dst = concat
    (
        "a:",a_len, ":",
        "{",
            s1, ";", s2, ";", s3, ";",
            "s:",s4_len_dst,":",
            char(34),
                s4_string_dst,
            char(34),
            ";", s5, ";", s6, ";",
        "}"
    );


################################################################################
# Copy results back to the original input table
################################################################################
#
# * Fill in the result in column "col_serial_data_dst_in"
#
set @ddl2=concat
(
    "update ", table_name_in, " 
    join 
       serial_tmp
       on
       serial_tmp.serial_data_src = ", table_name_in, ".",col_serial_data_src_in," 
    set
       ",table_name_in, ".",col_serial_data_dst_in, " = serial_tmp.serial_data_dst;"
);

prepare stmt from @ddl2;
execute stmt;
deallocate prepare stmt;

END

答案 1 :(得分:0)

serialize PHP函数将数据结构序列化为一个字符串表示形式,该字符串表示形式对PHP 唯一,并且可以使用反序列化将其反转为PHP对象。

MySQL不知道什么是PHP序列化。您不能仅使用SQL来做到这一点。

相关问题