Como ler campos virtuais do tipo memo no SQL


Os campos "memos" no protheus em sua maioria é do tipo virtual, pois este utiliza uma tabela "Descrições dos campos memo" (SYP) auxiliar para armazenar o conteúdo destes campos. Como exemplo, temos a tabela "Descrição Genérica de Produtos" (SB1). campo_memo_1 Para entender melhor, o campo B1_VM_P (Descrição em Português) é um campo virtual do tipo memo de tamanho 36, seu inicializador padrão utiliza a função E_MSMM para ler o conteúdo do campo B1_DESC_P (Código da descrição em português), campo este que contém o código chave que servirá de referência para localizar o descrição na tabela "Descrições dos campos memo" (SYP). [caption id="attachment_2935" align="aligncenter" width="453"]campo_memo_codigo Campo B1_DESC_P[/caption]   [caption id="attachment_2934" align="aligncenter" width="435"]campo_memo_campo Campo B1_VM_P[/caption]   [caption id="attachment_2933" align="aligncenter" width="468"]campo_memo_opcoes Campo B1_VM_P [/caption] Neste exemplo, para cada linha com 36 caracteres será uma nova linha na tabela SYP. Consultando no banco de dados, o registro fica conforme a imagem abaixo: consulta_syp


  Agora vamos ao que interessa, preciso montar uma consulta SQL que me mostre os registros da tabela SB1 e que me traga o conteúdo do campo memo do campo B1_DESC_P. É uma consulta simples, fazer um SELECT  na tabela SYP porém informando o código chave da tabela SB1, mas preciso trazer todas as linhas da SYP numa única linha e apresentá-la junto a consulta principal. Uma forma fácil de fazer isso é colocando uma sub-consulta SQL usando o comando "CASE" do SQL.
/*consulta simples a tabela SYP sem uso do CASE*/
SELECT * FROM SYP010 WHERE YP_CHAVE='000007' AND D_E_L_E_T_=''


/*consultar a tabela SYP com uso do CASE*/

--Consultando a primeira linha
SELECT  CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='001' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='001' AND D_E_L_E_T_='')) END
--Consultando a segunda linha
SELECT  CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='002' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='002' AND D_E_L_E_T_='')) END
--Consultando a terceira linha
SELECT  CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='003' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='003' AND D_E_L_E_T_='')) END

--Agora concatenando
SELECT 
(
--Consultando a primeira linha
SELECT  
RTRIM(CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='001' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='001' AND D_E_L_E_T_='')) END) +
--Consultando a segunda linha
RTRIM(CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='002' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='002' AND D_E_L_E_T_='')) END) +
--Consultando a terceira linha
RTRIM(CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='003' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE='000007' AND YP_SEQ='003' AND D_E_L_E_T_='')) END)
) AS MEMO

Mas como disse acima, a cada 36 caracteres é uma linha na tabela SYP, esta tabela possui um campo chamado YP_SEQ, ele contém a sequência de linhas. O campo memo pode ter várias e varias linhas, neste exemplo quero pegar apenas as 3 primeiras linhas. Consulta completa:
SELECT B1_COD,B1_DESC,B1_UM, 
 ( 
 	SELECT   
  	(CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE=B1_DESC_P AND YP_SEQ='001' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE=B1_DESC_P AND YP_SEQ='001' AND D_E_L_E_T_='')) END) +   
  	(CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE=B1_DESC_P AND YP_SEQ='002' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE=B1_DESC_P AND YP_SEQ='002' AND D_E_L_E_T_='')) END) +   
  	(CASE (SELECT COUNT(YP_TEXTO) FROM SYP010 WHERE YP_CHAVE=B1_DESC_P AND YP_SEQ='003' AND D_E_L_E_T_='') WHEN 0 THEN '' ELSE UPPER((SELECT YP_TEXTO FROM SYP010 WHERE YP_CHAVE=B1_DESC_P AND YP_SEQ='003' AND D_E_L_E_T_='')) END) 
 ) 
 AS DESCR_PORT
 FROM SB1010
 WHERE D_E_L_E_T_='' 
 ORDER BY B1_COD
A consulta retornar todos os registros incluindo o conteúdo do campo memo, concatenando as 3 linhas contidas na tabela SYP. Agora fica mais fácil apresentar campos memo dentro de um relatório no Protheus, pois o campo passa a ser do tipo caracter. Esperamos que tenha ajudado. abraços e até a próxima.