Olá pessoal…
Hoje vou mostrar um exemplo simples de como pegar o conteúdo de um campo MEMO do SQL Server via AdvPL (tanto o campo IMAGE, quanto pegando via SYP).
Existe dois tipos de campo MEMO no Protheus, um que usa o tipo IMAGE, sendo necessário converter para VARCHAR, e um que grava tudo na tabela SYP, quebrando linha pela expressão “\13\10”. Abaixo mostro um exemplo de cada.
Pelo campo tipo IMAGE
Pelo campo Image, basta converter como VARBINARY para VARCHAR, com o tamanho máximo de 8000 bytes. No exemplo abaixo, eu pego o campo B1_COD, o B1_DESC e converto o B1_X_OBS usando esse comando.
SELECT
B1_COD,
B1_DESC,
ISNULL(CAST(CAST(B1_X_OBS AS VARBINARY(8000)) AS VARCHAR(8000)),'') AS OBS
FROM
SB1010 SB1
Dessa forma, ele pega o conteúdo do B1_X_OBS, e converte para ser visível e possível a manipulação.
Update Março de 2024:
Pessoal, o grande Jonathan Silva ( LinkedIn ), passou um exemplo de como fazer a query, mas no banco de dados Oracle, segue abaixo:
SELECT
B1_COD,
B1_DESC,
REPLACE(REPLACE(utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(SB1.B1_X_OBS ,1024,1)),chr(13),''),chr(10),'') AS OBS --1024 é o número de caracteres que foi usado no exemplo
FROM
SB1010 SB1
Update Junho de 2025:
Pessoal, o grande Renan Martins ( LinkedIn ), precisou fazer a query num ambiente com PostgreSQL, então ele gentilmente cedeu dois exemplos:
/* Exemplo 1 */
SELECT
Z4_DCATEG,
Z4_DGRUPO,
Z4_DSUBGR,
Z4_REFER,
convert_from(Z4_REFER, 'UTF8') Z4_REFER,
convert_from(Z4_OBS, 'UTF8') Z4_OBS
FROM SZ4010
WHERE
D_E_L_E_T_ <> '*'
AND ENCODE(Z4_OBS, 'escape') NOT LIKE '%\\000%'
AND ENCODE(Z4_REFER, 'escape') NOT LIKE '%\\000%'
/* Exemplo 2 */
SELECT
Z4_DCATEG, Z4_DGRUPO, Z4_DSUBGR,
ENCODE(Z4_REFER, 'escape') Z4_REFER,
ENCODE(Z4_OBS, 'escape') Z4_OBS
FROM SZ4010
WHERE D_E_L_E_T_ <> '*'
AND Z4_CODIGO = '0008511'
Pela tabela SYP ou RDY (formas antigas)
A tabela SYP (ou RDY), era a forma antiga do Protheus controlar os campos MEMO (através da função MSMM), e nesse tipo, ele gerava vários registros com textos, por exemplo, a cada x caracteres gera uma nova linha, e para buscar isso via SQL Server, podemos fazer uma subquery, buscando pela chave da tabela, e montando a expressão em uma única linha com FOR XML PATH.
SELECT
UC_DTENCER AS DT_ENCER,
UC_DATA AS DT_2,
ISNULL(
CONVERT(VARCHAR(400), (
SELECT
RTRIM(SYP.YP_TEXTO)
FROM
SYP010 SYP
WHERE
SYP.YP_CHAVE = SUC.UC_CODOBS
AND SYP.YP_CAMPO = 'UC_CODOBS'
AND SYP.D_E_L_E_T_ = ' '
ORDER BY
YP_SEQ
FOR XML PATH ('')
)),
'') AS ATIVIDADE
FROM
SUC010 SUC
No exemplo acima, delimitamos que queremos até 400 caracteres, e fazemos uma subquery buscando os dados da SYP.
Obs.: Como lembrado pelo Leandro Michelsen nos comentários, pode ser que em algumas situações a quebra de linha esteja gravada como \13\10 tendo de ser tratado, como por exemplo com o comando replace.
Bom pessoal, por hoje é só.
Abraços e até a próxima.
O campo YP_TEXTO possui, em alguns casos, a string ‘\13\10’ indicando quebra de linha. Para isso ajustei a query adicionando a função REPLACE:
REPLACE(ISNULL (CONVERT(VARCHAR(4000),(SELECT RTRIM(SYP.YP_TEXTO) FROM SYP010 SYP WHERE SYP.YP_CHAVE = SB1.B1_DESC_GI AND SYP.YP_CAMPO = ‘B1_DESC_GI’ AND SYP.D_E_L_E_T_ = ‘ ‘ ORDER BY YP_SEQ FOR XML PATH (”) )), ‘ ‘),’\13\10’,”) AS DESCRI
Opa, muito obrigado pela contribuição Leandro.
Um grande abraço.