macs Posted March 9, 2021 Report Share Posted March 9, 2021 Boa tarde pessoal, Estou com problema ao realizar a alteração de estrutura de uma tabela utilizando a função Sr_ChangeStruct() com MySql O log de alteração que é gerado é esse: 09/03/2021 12:09:25: TIPO_EXAME Warning: DROP COLUMN: BACKUP_ (1091) Can't DROP 'backup_'; check that column/key exists - Can't DROP 'backup_'; check that column/key exists Eu acho que é criado este campo BACKUP_ automático, pois na estrutura da tabela não existe este campo. Qualquer alteração de estrutura de qualquer tabela, gera este erro, e o pior que este campo (backup_) é criado na tabela. Gostaria de saber se alguém já passou por isso. Obrigado pela atenção! Quote Link to comment Share on other sites More sharing options...
kapiaba Posted March 9, 2021 Report Share Posted March 9, 2021 Veja se ajuda: http://www.pctoledo.com.br/forum/viewtopic.php?f=42&t=13482 http://www.pctoledo.com.br/forum/viewtopic.php?f=4&t=10769 https://comp.lang.xharbour.narkive.com/l9MVXlaI/sr-changestruct-question Abs. Quote Link to comment Share on other sites More sharing options...
macs Posted March 9, 2021 Author Report Share Posted March 9, 2021 1 hora atrás, kapiaba disse: Veja se ajuda: http://www.pctoledo.com.br/forum/viewtopic.php?f=42&t=13482 http://www.pctoledo.com.br/forum/viewtopic.php?f=4&t=10769 https://comp.lang.xharbour.narkive.com/l9MVXlaI/sr-changestruct-question Abs. Não é meu caso! Quote Link to comment Share on other sites More sharing options...
sygecom Posted March 9, 2021 Report Share Posted March 9, 2021 Já passei por isso. renomeia essa coluna para o nome original que era antes da mudança em vez de deletar a coluna, e depois roda novamente a criação/alteração da estrutura para que o SALRDD consiga novamente criar essa coluna de backup e migrar os dados para a nova coluna que será criada. Quote Link to comment Share on other sites More sharing options...
macs Posted March 10, 2021 Author Report Share Posted March 10, 2021 Já fiz isso... mas não tem jeito! Pode ser problema da minha versão do SQLRDD. Quote Link to comment Share on other sites More sharing options...
sygecom Posted March 11, 2021 Report Share Posted March 11, 2021 Qual sua versão? Quote Link to comment Share on other sites More sharing options...
macs Posted March 11, 2021 Author Report Share Posted March 11, 2021 10 horas atrás, sygecom disse: Qual sua versão? Desculpa amigo, mas faz tempo que adquirir a SQLRDD. Existe alguma forma de saber a versão? Quote Link to comment Share on other sites More sharing options...
sygecom Posted March 12, 2021 Report Share Posted March 12, 2021 msginfo(SR_Version()) Quote Link to comment Share on other sites More sharing options...
macs Posted March 12, 2021 Author Report Share Posted March 12, 2021 12 horas atrás, sygecom disse: msginfo(SR_Version()) SQLRDD(EX) 9.0, Build 0015, MGMNT 1.72 Quote Link to comment Share on other sites More sharing options...
sygecom Posted March 13, 2021 Report Share Posted March 13, 2021 Mesma versão que uso aqui. Isso acontece quando está alterando algum campo já existente. No meu caso acontecia quando estava alterando uma estrutura e, alguem entra no sistema consultando/alterando registro da mesma tabela que está sendo alterado a estrutura. Para resolver isso antes de começar a mudar a estrutura uso: SR_SetFastOpen(.F.) e depois que terminou de alterar mudo novamente para: SR_SetFastOpen(.T.) Quote Link to comment Share on other sites More sharing options...
mkyx Posted March 13, 2021 Report Share Posted March 13, 2021 Bom dia, eu uso o alter table, sem problemas, com sqlrdd. Quote Link to comment Share on other sites More sharing options...
macs Posted March 15, 2021 Author Report Share Posted March 15, 2021 Em 13/03/2021 at 11:58, mkyx disse: Bom dia, eu uso o alter table, sem problemas, com sqlrdd. Eu gostaria que o RDD ficasse responsável por fazer qualquer tipo de manutenção nas tabelas. Se existe a função, ela teria que funcionar. Sei que a maioria dos comandos são iguais para qualquer banco de dados, mas eu não gostaria de ficar testando se o banco é ORACLE, ou Postgres, MySql, etc. Provavelmente o SQLRDD está prevendo todas as situações. Provavelmente deve ser a versão que estou utilizando. Alguém com versão mais recente poderia testar a função. Valeu! Quote Link to comment Share on other sites More sharing options...
macs Posted March 15, 2021 Author Report Share Posted March 15, 2021 Em 13/03/2021 at 10:07, sygecom disse: Mesma versão que uso aqui. Isso acontece quando está alterando algum campo já existente. No meu caso acontecia quando estava alterando uma estrutura e, alguem entra no sistema consultando/alterando registro da mesma tabela que está sendo alterado a estrutura. Para resolver isso antes de começar a mudar a estrutura uso: SR_SetFastOpen(.F.) e depois que terminou de alterar mudo novamente para: SR_SetFastOpen(.T.) Não existe outra pessoa utilizando, está acontecendo em minha base de dados. Mesmo assim vou testar conforme informado! Quote Link to comment Share on other sites More sharing options...
Ariston Santos Posted March 15, 2021 Report Share Posted March 15, 2021 Eu uso e também tive problema com Sr_ChangeStruct(), por isso criei minha própria função. Segue. Espero que ajude. aStr:={} AADD(aStr,{"CODIGO", "C", 13, 0}) // Código do item AADD(aStr,{"DESCRI", "C",120, 0}) // Descrição do item (No SISCOM só pega 60 caracteres) AADD(aStr,{"DTEXCL", "D", 08, 0}) // Data da exclusão - Para determinar quando eliminar deste bd, ex: 7 dias após a exclusão. l_Reindex := .F. IF ! SR_ExistTable( "itensdel_bd" ) TRY cComm := XB2SqlStr(aStr, "itensdel_bd") nErr := oSql:Execute( cComm ) CATCH oErr SysRefresh() MsgAlert("Erro ao tentar criar a tabela itensdel_bd."+CRLF+CRLF+; "Favor verificar as configurações de banco de dados.","Erro") IF FileWrite(ErroFile(), oErr:Description) WAITRUN( GetEnv( "ComSpec" )+" /C NOTEPAD .\errorlog\erro.txt", 0) ENDIF PostQuitMessage( 0 ) __QUIT() END else ChkStruct("itensdel_bd", "", "", aStr, oSql, nErr, nPos) ENDIF STATIC FUNCTION XB2SqlStr(aStr, cDBase) LOCAL cStrct cStrct := "CREATE TABLE `"+LOWER(cDBase)+"` (" FOR nF := 1 TO LEN(aStr) IF LOWER(aStr[nF,1]) != "sr_recno" IF nF > 1 ; cStrct += ", " ; ENDIF // Mais de um campo cStrct += "`"+LOWER(aStr[nF,1])+"` "+SetFType(aStr[nF,2],aStr[nF,3],aStr[nF,4]) ENDIF NEXT IF LEN(aStr) > 0 ; cStrct += ", " ; ENDIF // Já acrescentado algum campo cStrct += "`sr_recno` BIGINT (15) NOT NULL UNIQUE AUTO_INCREMENT)" // Sempre criar o 'sr_recno' no final, para compatibilizar com SQLRDD RETURN( cStrct ) STATIC FUNCTION SetFType(cTipo,nSize,nDeci) LOCAL cFType IF cTipo = "C" ; cFType := "char("+ALLTRIM(STR(nSize))+")" ELSEIF cTipo = "M" ; cFType := "mediumblob" ELSEIF cTipo = "N" ; cFType := "double("+ALLTRIM(STR(nSize))+","+ALLTRIM(STR(nDeci))+")" ELSEIF cTipo = "L" ; cFType := "tinyint(4)" ELSEIF cTipo = "D" ; cFType := "date" ENDIF RETURN(cFType) STATIC FUNCTION ChkStruct(cTable, cUniq, cAuto, aStrct, oSql, nErr, nPos) LOCAL lChangd, cComm, aNewStr, aOldStr, aChange, aImport, cImport, aArray := {}, cTmpTable := cTable+"_old" IF ! l_CkStr ; RETURN .F. ; ENDIF // Não deve verificar a estrutura dos dados. Apenas criar as novas tabelas cDBName := UPPER( SR_GetConnectionInfo(, SQL_DBMS_NAME ) ) IF ! ("FIREBIRD" $ cDBName) // Não estou conectado ao Firebird. Firebird não aceita RENAME TABLE - http://www.firebirdfaq.org/faq363/ aNewStr := aStrct nScan := ASCAN(aNewStr, {|nC|nC[1]="sr_recno"}) IF nScan = 0 AADD(aNewStr, {"sr_recno", "N", 15, 0}) // SQLRDD acrescenta este campo ao criar a tabela ENDIF cSay := "Verificando a tabela '"+cTable+"'" oSay:SetText(cSay) ; oSay:Refresh() IF ! l_CkStr ; RETURN .F.; ENDIF // Obter a estrutura da tabela atual. nLenTb := 0 STORE 0 TO nErr, nPos TRY cComm := "SELECT * FROM "+cTable+" LIMIT 1" oSql := SR_GetConnection() nErr := oSql:execute( cComm ) oSql:iniFields(.f.) aOldStr := oSql:aFields // Para pegar a estrutura nLenTb := LEN(aArray) * MyXBrowse(aOldStr, "Estrutura atual") CATCH SysRefresh() ; MsgAlert("Não foi possível testar a tabela '"+cTable+"'", +ProcName()+"("+AllTrim(Str(ProcLine()))+")") RETURN .F. END TRY // Comparar com a estrutura de aStrct lChangd := .F. aChange := {} aImport := {} cImport := "" TRY FOR nX := 1 TO LEN(aNewStr) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum. cFild:=Lower(aNewStr[nX,1]) cType:=aNewStr[nX,2] cSize:=STRZERO(aNewStr[nX,3], 4) cDeci:=STRZERO(aNewStr[nX,4], 3) nElem := ASCAN(aOldStr, {|aNro| Lower(aNro[1]) == cFild}) IF nElem > 0 if cFild != "sr_recno" // Não considerar erro de estrutura deste IF cType != aOldStr[nElem,2] .OR. ; cSize != STRZERO(aOldStr[nElem,3], 4) .OR. ; cDeci != STRZERO(aOldStr[nElem,4], 3) lChangd := .T. // Mudou o tamanho de um campo aadd(aChange, {cFild, "Modificou a estrutura"}) ENDIF endif ELSE lChangd := .T. // Foi removido algum campo aadd(aChange, {cFild, "Campo acrescentado"}) ENDIF NEXT FOR nX := 1 TO LEN(aOldStr) // Verifica se foi excluindo algum compo cFild := Lower(aOldStr[nX,1]) nElem := ASCAN(aNewStr, {|aNro| Lower(aNro[1]) == cFild}) IF nElem = 0 lChangd := .T. // Algum campo foi removido aadd(aChange, {cFild, "Campo removido"}) ELSE AADD(aImport, cFild) // Para pegar só os campos que existem nas duas tabelas. ENDIF NEXT IF lChangd // Determinar quais campos serão importados da tabela temporária FOR nX := 1 TO LEN(aImport) IF Lower(aImport[nX]) != "sr_recno" // Apenas um teste IF ! EMPTY(cImport) ; cImport += ", " ; ENDIF cImport += aImport[nX] // Pegar só os campos que existem nas duas tabelas. ENDIF NEXT ENDIF CATCH SysRefresh() ; MsgAlert("Não foi possível testar a tabela '"+cTable+"'", +ProcName()+"("+AllTrim(Str(ProcLine()))+")") RETURN .F. END TRY IF ! lChangd ; RETURN .F. ; ENDIF IF SR_ExistTable( cTmpTable ) cComm := "DROP TABLE "+cTmpTable TRY nErr := oSql:Execute( cComm ) if nErr == 0 SysRefresh() ; MsgAlert("Executou "+cComm, "Ok") else MsgAlert("Não foi preciso executar "+cComm, "Retorno: "+cValToChar(nErr)) endif CATCH SysRefresh() ; MsgAlert("Não foi possível excluir a tabela '"+cTmpTable+"'", "Erro...") RETURN .F. END TRY ENDIF cComm := "ALTER TABLE "+cTable+" RENAME "+cTmpTable nErr := oSql:Execute( cComm ) l_Err := .F. TRY cComm := XB2SqlStr(aStrct, cTable) nErr := oSql:Execute( cComm ) CATCH oErr l_Err := .T. END TRY IF l_Err cComm := "ALTER TABLE "+cTmpTable+" RENAME "+cTable nErr := oSql:Execute( cComm ) MsgAlert("Erro ao tentar criar a nova a tabela: Executado RollBack '"+cTable+"'.","Erro") ; SysWait(1) RETURN .F. ENDIF IF ! EMPTY(cUniq) TRY cSql := "ALTER TABLE "+cTable+" ADD UNIQUE ("+cUniq+")" nErr := oSql:Execute(cSql) CATCH END TRY ENDIF IF ! EMPTY(cAuto) TRY cSql := "ALTER TABLE "+cTable+" MODIFY "+cAuto+" int NOT NULL AUTO_INCREMENT" nErr := oSql:Execute(cSql) CATCH END TRY ENDIF // Importar dados da tabela temporária IF ! empty(cImport) cComm := "INSERT INTO "+cTable+" ("+cImport+") SELECT "+cImport+" FROM "+cTmpTable nErr := oSql:Execute( cComm ) IF nErr != 0 MsgAlert("Erro ao tentar recuperar os dados da tabela '"+cTmpTable+"'.","Erro") ; SysWait(0.5) ENDIF ENDIF // Excluir a tabela temporária cComm := "DROP TABLE "+cTmpTable nErr := oSql:Execute( cComm ) ELSE // Estou usando Firebird, que não aceita RENAME TABLE - http://www.firebirdfaq.org/faq363/ USE &(cTable) EXCLUSIVE VIA "SQLRDD" a_Str := dbStruct() lChangd := .F. IF LEN(a_Str) != LEN(aStrct) lChangd := .T. // Campos foram removidos ou acrescentados ELSE FOR nRow := 1 TO LEN(a_Str) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum. cFld := Lower(a_Str[nRow,1]) cTyp := a_Str[nRow,2] cSze := STRZERO(a_Str[nRow,3], 4) nDec := ALLTRIM(STR(a_Str[nRow,4])) nElem := ASCAN(aStrct, {|aNro| UPPER(ALLTRIM(aNro[1])) == UPPER(ALLTRIM(cFld))}) IF nElem > 0 IF UPPER(cFld) != "SR_RECNO" // Não considerar erro de estrutura deste IF cTyp != aStrct[nElem,2] .OR. ; nDec != ALLTRIM(STR(aStrct[nElem,4])) // Não verificar nSize em campos numéricos no Firebird. Tamanho fixo: 19 lChangd := .T. // Mudou a estrutura ENDIF IF cTyp == "C" .AND. cTyp == aStrct[nElem,2] IF cSze <> STRZERO(aStrct[nElem,3], 4) // Considerar tamanho em campos tipo caractere lChangd := .T. // Mudou a estrutura ENDIF ENDIF ENDIF ELSE lChangd := .T. // Campo renomeado, ou houve exclusão de um e inclusão de outro. ENDIF NEXT ENDIF IF lChangd IF ! SR_ChangeStruct(cTable, aStrct) // Via SR_ChangeStruct(), indexes are automatically dropped if columns change lChangd := .F. SysRefresh() ; MsgAlert("Houve um erro ao tentar modificar a estrutura de "+cTable,"Aviso") ENDIF ENDIF dbCloseArea() ENDIF RETURN( .t. ) *----------( Compara dois arrays e retorna .T. se houver diferença )----------* FUNCTION ArrayCheck(aArr1, aArr2) LOCAL cArr1 := "", cArr2 := "", cNew := "", cOld := "" LOCAL _lDif := .F.; _aAdd := {}; _aDif := {}; _aDel := {} FOR n1 := 1 TO LEN(aArr1) aLin := aArr1[n1] cNew := "" cOld := "" if ! empty(cNew) ; cNew += CRLF ; ENDIF FOR nL := 1 TO LEN(aLin) cArr1 += ALLTRIM(CStr(aLin[nL])) cNew += ALLTRIM(CStr(aLin[nL])) NEXT n_Id := aArr1[n1,1] aOld := {} nScn := ASCAN(aArr2,{|nCel|nCel[1]==n_Id}) IF nScn > 0 // Se achar, verificar se houve modificação aOld := aArr2[nScn] if ! empty(cOld) ; cOld += CRLF ; ENDIF FOR nL := 1 TO LEN(aOld) cOld += ALLTRIM(CStr(aOld[nL])) NEXT ELSE // Senão, foi excluído AADD(_aDel, aLin) // Gerar linha com o registro excluido ENDIF IF cNew != cOld AADD(_aDif, aLin) // Gerar linha com o registro modificado ENDIF NEXT FOR n2 := 1 TO LEN(aArr2) // Processar anteriores só para determinar se houve exclusão. aLin := aArr2[n2] FOR nL := 1 TO LEN(aLin) cArr2 += ALLTRIM(CStr(aLin[nL])) NEXT n_Id := aArr2[n2,1] nScn := ASCAN(aArr1,{|nCel|nCel[1]==n_Id}) IF nScn = 0 // Se não achar, foi acrescentado AADD(_aAdd, aLin) ENDIF NEXT IF LEN(_aAdd) > 0 .OR. LEN(_aDif) > 0 .OR. LEN(_aDel) > 0 _lDif := .T. ENDIF IF _lDif cInfo := "Houve alteração de item" IF LEN(_aDif) > 0 cInfo += CRLF+CRLF+"Item diferente: "+CRLF FOR nL := 1 TO LEN(_aDif) aLin := _aDif[nL] FOR nC := 1 TO LEN(aLin) cInfo += ALLTRIM(CStr(aLin[nC])) NEXT cInfo += CRLF NEXT ENDIF IF LEN(_aAdd) > 0 cInfo += CRLF+CRLF+"Item novo: "+CRLF FOR nL := 1 TO LEN(_aAdd) aLin := _aAdd[nL] FOR nC := 1 TO LEN(aLin) cInfo += ALLTRIM(CStr(aLin[nC])) NEXT cInfo += CRLF NEXT ENDIF IF LEN(_aDel) > 0 cInfo += CRLF+CRLF+"Item excluido: "+CRLF FOR nL := 1 TO LEN(_aDel) aLin := _aDel[nL] FOR nC := 1 TO LEN(aLin) cInfo += ALLTRIM(CStr(aLin[nC])) NEXT cInfo += CRLF NEXT ENDIF ENDIF RETURN _lDif Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.